jq入門:macOSでJSONをコマンドラインで操作する

スポンサーリンク

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