jq入門:macOSでJSONをコマンドラインで操作する
はじめに
jq はコマンドラインでJSONを整形・抽出・変換するツールです。APIのレスポンスをパイプで渡したり、JSONファイルから特定のフィールドだけ取り出したりする場面で使います。
インストール
brew install jq
バージョン確認:
jq --version # jq-1.7.1
基本の使い方
JSON を整形する
パイプで渡すだけで色付き・インデント済みで表示されます。
echo '{"name":"田中","age":30}' | jq .
{ "name": "田中", "age": 30 }
ファイルを直接読む場合:
jq . data.json
フィールドを取得する
.キー名 でフィールドを取り出します。
echo '{"name":"田中","age":30}' | jq .name
# "田中"
echo '{"name":"田中","age":30}' jq .age
# 30
クォートなしで取り出したい場合は -r(raw output)を使います。
echo '{"name":"田中"}' | jq -r .name
# 田中(クォートなし)
ネストしたフィールドを取得する
echo '{"user":{"name":"田中","email":"tanaka@example.com"}}' | jq .user.name
# "田中"
echo '{"user":{"name":"田中","email":"tanaka@example.com"}}' | jq .user.email
# "tanaka@example.com"
配列から取得する
echo '[1,2,3]' | jq .[0] # 1 echo '[1,2,3]' | jq .[-1] # 3(末尾) echo '[1,2,3]' | jq .[1:3] # [2, 3](スライス)
配列の全要素を展開する
echo '[{"name":"田中"},{"name":"鈴木"}]' | jq .[].name
# "田中"
# "鈴木"
パイプ
jq の出力を次のフィルタに渡せます。
echo '{"users":[{"name":"田中","age":30},{"name":"鈴木","age":25}]}' \
| jq '.users[] | .name'
# "田中"
# "鈴木"
よく使うフィルタ
keys・values
echo '{"name":"田中","age":30}' | jq keys
# ["age", "name"]
echo '{"name":"田中","age":30}' | jq values
# ["田中", 30]
length
echo '[1,2,3,4,5]' | jq length
# 5
echo '{"name":"田中","age":30}' | jq length
# 2(キーの数)
select(条件でフィルタ)
echo '[{"name":"田中","age":30},{"name":"鈴木","age":25}]' \
| jq '.[] | select(.age >= 30)'
# {"name": "田中", "age": 30}
map(全要素に適用)
echo '[1,2,3]' | jq 'map(. * 2)'
# [2, 4, 6]
echo '[{"name":"田中","age":30},{"name":"鈴木","age":25}]' \
| jq 'map(.name)'
# ["田中", "鈴木"]
has(キーの存在確認)
echo '{"name":"田中","age":30}' | jq 'has("name")'
# true
echo '{"name":"田中","age":30}' | jq 'has("email")'
# false
type
echo '"hello"' | jq type # "string" echo '42' | jq type # "number" echo '[]' | jq type # "array"
オブジェクトの構築
{} で新しいオブジェクトを作れます。
echo '{"name":"田中","age":30,"email":"tanaka@example.com"}' \
| jq '{name, age}'
# {"name": "田中", "age": 30}
キー名を変えたい場合:
echo '{"name":"田中","age":30}' \
| jq '{氏名: .name, 年齢: .age}'
# {"氏名": "田中", "年齢": 30}
curl と組み合わせる
APIのレスポンスをそのままパイプで渡せます。
curl -s https://api.github.com/users/octocat | jq .name
# "The Octocat"
curl -s https://api.github.com/users/octocat | jq '{name: .name, repos: .public_repos}'
# {"name": "The Octocat", "repos": 8}
複数の値をまとめて出力する
echo '{"name":"田中","age":30}' | jq '[.name, .age]'
# ["田中", 30]
# CSV形式で出力
echo '[{"name":"田中","age":30},{"name":"鈴木","age":25}]' \
| jq -r '.[] | [.name, (.age | tostring)] | join(",")'
# 田中,30
# 鈴木,25
null の扱い
存在しないキーを参照すると null が返ります。
echo '{"name":"田中"}' | jq .age
# null
null を除外したい場合は select を使います。
echo '[{"name":"田中","age":30},{"name":"鈴木"}]' \
| jq '.[] | select(.age != null)'
# {"name": "田中", "age": 30}
よく使うオプション
| オプション | 説明 |
|---|---|
-r |
文字列からクォートを取り除いて出力 |
-c |
コンパクト(1行)で出力 |
-n |
入力を読まずにフィルタを実行 |
-e |
出力が false / null のとき終了コード1 |
--arg name value |
変数を定義して使う |
--argjson name value |
JSON値として変数を定義 |
# --arg の例
echo '{"name":"田中"}' | jq --arg key name '.[$key]'
# "田中"
まとめ
| やりたいこと | jq フィルタ |
|---|---|
| 整形表示 | . |
| フィールド取得 | .key |
| ネスト取得 | .a.b |
| 配列の要素 | .[0] / .[-1] |
| 配列全展開 | .[] |
| 条件フィルタ | select(.key == "value") |
| 全要素に適用 | map(...) |
| 新オブジェクト作成 | {key: .field} |
| クォートなし出力 | -r |
| 1行出力 | -c |