JSONにルールをチョイ足しして実行できるJSON拡張記法 SushiJSON

logo.png

概要

JSON自体はそのままだと値にしかならないが、

JSONに外部文字列を与えて、単純なパーサーで実行できるようにした。


その定義とパーサーとサンプルの実行実装をまとめたものがこれ。

https://github.com/sassembla/SushiJSON



できること

・JSONの外側に文字列を追加するだけで形成可能

・自分用のAPIを定義して実行できる

・APIから別のAPIの実行が可能


なので、JSONをデータとして受取って動作する機構があった時、

・受取ったデータから特定のパラメータを取り出して動作する

みたいなのが、


・受取ったデータを元にダイレクトに動作する

という形にできる。危ない。



使用例

SublimeSocket3

https://github.com/sassembla/SublimeSocket3

Sublime Text のAPIを、この記法でWebSocket越しに実行できるようにした。

対応するSTのAPIを書き、順などを指定して遠隔実行したり、内部にフィルタなどを構築できる。



ST2用のSublimeSocketにマージ中。



記法サンプル

ファイルか、ネットワーク経由のデータで下記みたいな記法のものを送り込み

helloworld.txt or data via network


helloWorld: {←最外部はquote無し、:付き。 :以降はJSON。

"message": "hello world!"

}




実装サンプル


こんなかんじの実装を書く事で


data = ファイルデータ


def runAPI(command, params):


# print "message" value

if command == "helloWorld":

assert "message" in params, "helloWorld requires 'message' param."


print(params["message"])



// run

[runAPI(command, params) for command, params in SushiJSONParser.parseFromFile(data)]




実行結果サンプル

動作、結果がでる。



hello world!




特徴とか

JSONをAPIへのパラメータとして使用する

APIName:{JSON}



APIName: {

"key": "value"

}



APIName: から先がJSON

JSONとして解釈できさえすればOKなので、



APIName: {

"keys": [

"key1",

"key2",

"key3"

],

"values": {

"key1": "value1",

"key2": "value2",

"key3": "value3"

},

"something": [

{

"key": "value",

"array": [

"key1",

100,

false

]

}

]

}


など、配列入れたり辞書いれたり値入れたり、自由にできる。

まあこんな引数で動作するAPI厭だが。



順解釈して実行可

parserからだと、 -> で接続したAPIを順に解釈して実行できる。

単純な順実行で、値の共有などは無し。



APIName: {

"key": "value"

}

->APIName2: {

"key2": "value2"

}




ネスト可

APIの実行後、内部から次のAPIを実行する機構として、"selectors"キーワードを使用する。

selectorsの中身は順番で実行されるが、同一selectors内にあるAPI間の値の引き渡しは無し。



APIName1: {

"key1": "value1"

"selectors": [

{

"APIName2": {

"key2": "value2"

}

},

{

"APIName3": {

"key3":"value3"

}

}

]

}




API間の値の受け渡しに対してグローバル無し+明示的

selectorsを介して実行するAPIのパラメータ部分へと、キーを指定してキー+値の代入ができる。

代入するキーを明示しないと代入されない。


APIName1: {

"selectors": [

{

"APIName2<-APIName1の結果のキー": {

//  + APIName1の結果のキー: APIName1の結果

}

}

]

}



処理系実装がどの言語でもたぶん簡単

処理系はJSONのSerialize/Deserializeが用意されてる言語なら200行くらいで実装できるはず。

ジェネレータがあれば逐次実行も容易。

Pythonでの処理系はこんな感じ。

https://github.com/sassembla/SushiJSON/blob/master/parser/SushiJSON.py


動作系の実装がどの言語でも割と簡単

パースとAPIのネスト実行まで含めてこんなかんじに書ける。

https://github.com/sassembla/SushiJSON/blob/master/parser/runtimeSample/SampleSushiJSONRunner.py#L18