jqでJSONを整形してる時に、深いネストのキーを検索する方法のメモ
ただ、この記事はjq歴3時間のド素人書いたやつなので、もっといい方法が絶対あるはず(と言うか誰かおしえてください)
#キー名でのフィルターのかけ方
例えば以下のJsonファイルで「key1」というキーを持つ文字列だけを取り出したい場合は以下のように書く。
{
"key1":{
"key2":"value1",
"key3":"value2"
},
"foo":"bar"
}
$ jq '.key1' test.json
{
"key2": "value1",
"key3": "value2"
}
要するに.hogeって書けば、ドットの後に続けた文字列のキーに該当する値を返してくれる。これは連続で書くこともできて、例えば以下のように書くと、ネストを掘りながらフィルターを掛けることができる。
$ jq '.key1.key2' test.json
"value1"
ただしこのフィルターは1階層目のキーしか見てくれないので、例えば以下のように書いてしまうとnullが帰ってきてしまう。
$ jq '.key2' test.json
null
つまりこのフィルターで値をとってきたい場合、「抽出したいキーの名前はわかってるんだけど、その上の階層でどんなキーが指定されてるのかわからなくて、そもそも何階層目にあるかわからない」って時には上手く動かない。
要するにどんな階層にいても目的のキーを抽出してくれるgrep的な何かがほしいわけです。(まあそれこそgrep使えばいいのかもしれないけど)。
#recurseを使う
resurseってのはJsonのオブジェクトの中身を再帰的に展開してくれるフィルター。たぶん見てみるのが一番早いと思う。
{
"key1":{
"key2":"value1",
"key3":"value2"
},
"foo":"bar"
}
$ jq 'recurse' test.json
{
"key1": {
"key2": "value1",
"key3": "value2"
},
"foo": "bar"
}
{
"key2": "value1",
"key3": "value2"
}
"value1"
"value2"
"bar"
とまあこんな感じでオブジェクトの中身を展開してくれる。こいつを使うと、どんなに深いネストの中にあるキーで強制的に1階層目に持ってこれるわけです。代わりに余計なものがいっぱいくっついてくるけど。
なので、select関数を使って、「key2」を一階層目のキーに持たないオブジェクトを削除する。
{
"key1":{
"key2":"value1",
"key3":"value2"
},
"foo":"bar"
}
$ jq 'recurse | select(.key2)' test.json
{
"key2": "value1",
"key3": "value2"
}
ここでの「|」は、シェルの「|」とほぼ同じ意味で、左の出力結果をそのまま右のフィルターの入力パラメータに利用する事ができる。
ここまでくればあとはフィルターをかけるだけ
$ jq 'recurse | select(.key2) | .key2' test.json
"value1"
略式でこう書くこともできる。
$ jq 'recurse | select(.key2).key2' test.json
"value1"
こんな感じで無事「key2」の値を取ってくることができた。
ちなみにselect関数を使わないと、以下の様な感じで「key2」を持たないオブジェクトに対するフィルター結果であるnullが残ってしまう。
{
"key1":{
"key2":"value1",
"key3":"value2"
},
"foo":"bar"
}
$ jq 'recurse | .key2' test.json
null
"value1"
#recurse応用
recurse関数は以下のように再帰的にフィルターをかけながら展開することもできる(と言うかこっちが本来の使い方?)
{
"key1":{
"key2":"value1",
"key3":"value2"
},
"foo":"bar"
}
$ jq 'recurse(.key1)' test.json
{
"key1": {
"key2": "value1",
"key3": "value2"
},
"foo": "bar"
}
{
"key2": "value1",
"key3": "value2"
}
おんなじキー名が連続してネストされているような場合に使うらしい。そんな時あるのかな・・・
より詳しい使い方は公式サイトのマニュアル見てください。
日本語訳してくれているページも参考になりました。感謝
ブラウザでjqを試し打ちできるページもあるので、いろいろ遊ぶと楽しいです。