jqの使い方
jqとは、jsonの解析を行うコマンドです。
APIの応答のjsonを解析するのに使うのですが、構文を忘れがちなので、個人的によく使うものだけ、覚え書き的に書き出しています。
サンプルjson
API応答のjsonという形を再現するために、テキストファイルにjson形式でデータを書いたものを用意しました。
# test.json
{
"title": "User Information",
"data": [
{
"name": "John Doe",
"age": 30,
"hobbies": ["football", "reading", "coding"]
},
{
"name": "Jane Doe",
"age": 28,
"hobbies": ["painting", "music", "traveling"]
}
]
}
jsonをjqに読み込む
標準出力をパイプで渡します。
cat test.json | jq
cat test.json | jq .
{
"title": "User Information",
"data": [
{
"name": "John Doe",
"age": 30,
"hobbies": [
"football",
"reading",
"coding"
]
},
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
]
}
元のファイルとほとんど同じですが、値の並べ方や括弧の位置が調整されています。
APIの出力ではjsonなのに1行で表示されてしまう、といった場合に、jqを通すことで表示の整形が可能です。
指定した項目を表示
項目名を書くことで、その項目の値を取り出すことができます。
cat test.json | jq .title
"User Information"
値のダブルクォートを消す
r オプションを付けると、ダブルクォーテーションを消すことができます。
取り出した値を変数に入れて使うときなどに便利です。
cat test.json | jq -r .title
User Information
配列の場合も項目の取り方は同じ
項目の中で値が配列になっていても、項目の取り出し方は変わりません。
cat test.json | jq .data
[
{
"name": "John Doe",
"age": 30,
"hobbies": [
"football",
"reading",
"coding"
]
},
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
]
取り出した値は、配列になっています。
配列内の件数をカウント
取り出した配列の中のデータの数をカウントすることができます。
cat test.json | jq '.data | length'
2
配列の中身を取り出す
取り出した値が配列のときは、その中身を取り出すことができます。
今回のサンプルのように、配列の中にさらにjsonが入っている場合など、さらに解析が必要な場合に役立ちます。
cat test.json | jq .data[]
{
"name": "John Doe",
"age": 30,
"hobbies": [
"football",
"reading",
"coding"
]
}
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
配列の中身が取り出されて、2件のデータが列挙された状態になりました。
配列なので、何番目か指定して値を取り出すこともできます。
[0] で先頭のデータが取り出されます。
cat test.json | jq .data[0]
{
"name": "John Doe",
"age": 30,
"hobbies": [
"football",
"reading",
"coding"
]
}
cat test.json | jq .data[1]
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
配列内のjson項目を取り出す
配列内のjsonにある項目を指定して、その値を取り出すことができます。
cat test.json | jq .data[].age
30
28
配列に入っていたうちの、どのデータなのか絞り込まれていない場合は、全て取り出されます。
数値の合計を表示
取り出した値が数値の場合、その合計値を計算することができます。
cat test.json | jq .data[].age | jq -s add
58
今回のサンプルでは年齢を合計しているので、あまり意味はありませんが、最終的に合計値を算出したいデータの場合、他のコマンドを使わずに完結することができます。
特定のデータのみを抽出
条件を設定して、それを満たすデータのみを抽出することができます。
今回のサンプルでは、趣味に音楽がある人のみを抽出しています。
cat test.json | jq .data[] | jq 'select(.hobbies[] | contains("music"))'
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
指定どおり、hobbiesの配列内にmusicという文字列のある人のデータだけが抽出されました。
jqの中でパイプすることも可能
ここまでの例では基本的に、jqの結果をjqにパイプしていましたが、jqの中でパイプすることが可能です。
どちらの書き方でも結果は同じですが、1回のコマンドにまとめようとすればするほど、括弧やクォートの扱いが煩雑になっていきます。
cat test.json | jq '.data[] | select(.hobbies[] | contains("music"))'
{
"name": "Jane Doe",
"age": 28,
"hobbies": [
"painting",
"music",
"traveling"
]
}
抽出した結果から、指定の項目のみを表示
抽出結果がjsonなら、そこからさらにjqの処理をかけることができます。
サンプルから、趣味に音楽がある人のみを抽出して、その人の名前のみを表示させます。
cat test.json | jq '.data[] | select(.hobbies[] | contains("music")) | .name'
"Jane Doe"
このようにすることで、特定の条件に当てはまるデータ内の必要項目のみを取り出す、といった使い方ができます。
二つの項目を表示
ここまでの例では、1つの項目だけを取り出してきましたが、複数の項目を指定することも可能です。
cat test.json | jq .data[] | jq '.name, .age'
cat test.json | jq '.data[] | .name, .age'
"John Doe"
30
"Jane Doe"
28
配列内の全データから、名前と年齢を取り出すことができました。
最後に
jqにはもっといろいろな機能がありますが、ここに書いたものだけでも、だいぶいろいろな分析ができます。
APIを叩くとjsonで返るからjqで何とかしないと、と頭を悩ませることが多かったのですが、何とか取り組んだおかげで、jqやjsonだけでなく、配列についても理解を深められてよかったです。
この記事が気に入ったらサポートをしてみませんか?