joとの比較で負けている気になったのでmkdictにblockを入れてみた
昨日の記事でjoと比較してみたのだけれど。ネストが深いJSONを作るのは楽でも、同じ階層の複数フィールドに値をもたせたJSONを作るのが大変だった。癪だったのでblockという概念を導入してみた。
同じ階層に複数のフィールド
例えば以下の様なJSONを作りたいとする。obの階層にname,ageという2つのフィールドがある。
{ "ob": { "age": 20, "name": "foo" } }
このとき今までのmkdictでは以下のように記述する必要があった。
$ dictknife mkdict ob/age 20 ob/name foo
joではシェル上で直接ネストして呼び出すことで以下の様に書ける。
$ jo -p ob=$(jo age=20 name=foo)
一方mkdictでは、深い階層のフィールドが単一であれば"/"で繋げていけば良いので ob/name foo
みたいに手軽に記述できるのだけれど(よりネストした階層についても ob/father/name bar
みたいに)、同じ階層に複数のフィールドをもたせたい時にちょっと不便だった。例えば今回はob/age
とob/name
と毎回共通のprefix(?)を書く必要が出てしまう。
block
そんなわけでblockという概念を導入した。blockは"{"と"}"で記述されるもの。例えば先程のコードをblockを使って記述すると以下の様になる。
# 先程のコード $ dictknife mkdict ob/age 20 ob/name foo # blockを使ったコード $ dictknife mkdict ob { age 20 name foo }
注意点として、"{"と"}"と他の引数との間には必ず空白が必要。シェルのtestコマンドと同様のイメージ(if [ -z "foo" ]
のようなもののこと)。
なので以下の様なコードはNG。ただし現状の実装では構文エラーにはならない。
$ dictknife mkdict ob {age 20 name foo } dictknife mkdict ob { age 20 name foo}
複雑なネストも
もちろん複雑なネストにも対応している。
深いネストでも。
$ dictknife mkdict a/b/c/ob { name foo age 20 } { "a": { "b": { "c": { "ob": { "name": "foo", "age": 20 } } } } }
blockの中にblockがあっても。
$ dictknife mkdict a/b { x/ob { name foo age 20 } y/ob { name boo } } id 1 { "a": { "b": { "x": { "ob": { "name": "foo", "age": 20 } }, "y": { "ob": { "name": "boo" } } } }, "id": 1 }
変数の参照と組わせる
変数の参照と組み合わせると便利。
$ dictknife mkdict @father { name A age 20 } @mother { name B age 20 } { name X age 0 father "&father" mother "&mother" } ";" { name Y age 1 father "&father" mother "&mother" } [ { "name": "X", "age": 0, "father": { "name": "A", "age": 20 }, "mother": { "name": "B", "age": 20 } }, { "name": "Y", "age": 1, "father": { "name": "A", "age": 20 }, "mother": { "name": "B", "age": 20 } } ]
ヒアドキュメントでも。
$ dictknife mkdict << EOS @father { name A age 20 } @mother { name B age 20 } name X age 0 father "&father" mother "&mother" name Y age 1 father "&father" mother "&mother" EOS
まぁヒアドキュメントを使えるような状況なら素直にJSONを書いたほうが良いかもしれない。
導入に伴い変数にスコープを導入
blockの導入に伴い変数にスコープを導入した。一応blockの内部で同名の変数はシャドウイングされるし、外側の環境の変数にアクセスできる。
$ dictknife mkdict @v 10 x0 "&v" x1 { v "&v" } x2 { @v 20 v "&v" } x3 { v "&v" } x4 { v "&v" @v 100 y { v "&v" } } @v 11 x5 "&v" { "x0": 10, "x1": { "v": 10 }, "x2": { "v": 20 }, "x3": { "v": 10 }, "x4": { "v": 10, "y": { "v": 100 } }, "x5": 11 }