最頻出10項目
| やりたいこと | コマンド |
|---|---|
| JSONを整形 | jq '.' data.json |
| キーを取得 | jq '.name' data.json |
| 配列の先頭 | jq '.[0]' data.json |
| 配列を展開 | jq '.[]' data.json |
| 条件で絞る | jq '.[] | select(.active)' data.json |
| 配列を変換 | jq 'map(.name)' data.json |
| キー一覧 | jq 'keys' data.json |
| 文字列を生で出力 | jq -r '.name' data.json |
| 1行JSONで出力 | jq -c '.[]' data.json |
| シェル変数を渡す | jq --arg name "$name" '.name = $name' data.json |
jq は入力JSONを読み、結果を標準出力へ書きます。通常は元ファイルを直接変更しません。
値を取り出す
次のJSONを例にします。
{
"name": "Ada",
"profile": { "age": 18 },
"tags": ["web", "js"]
}
| フィルタ | 結果 |
|---|---|
. | 入力全体 |
.name | "Ada" |
.profile.age | 18 |
.missing? | キーがなくてもエラーを抑える |
.tags[0] | "web" |
.tags[-1] | "js" |
.tags[] | 配列要素を1件ずつ出力 |
.name, .profile.age | 複数の結果を出力 |
パイプ | は左の出力を右の入力へ渡します。
jq '.users[] | .name' data.json
selectで絞り込む
jq '.users[] | select(.active == true)' data.json
jq '.users[] | select(.age >= 18 and .role == "student")' data.json
jq '.users[] | select(.name | startswith("A"))' data.json
配列としてまとめたい場合は全体を [...] で囲みます。
jq '[.users[] | select(.active)]' data.json
mapで変換する
jq '.users | map(.name)' data.json
jq '.users | map({id, name})' data.json
jq '.scores | map(. * 2)' data.json
map(filter) は配列の各要素へフィルタを適用し、新しい配列を返します。.users[] | ... は結果を1件ずつ出す点が異なります。
配列の確認と集計
| フィルタ | 用途 |
|---|---|
length | 要素数を返す |
first / last | 最初 / 最後の要素 |
sort | 値を並べ替える |
sort_by(.age) | 指定キーで並べ替える |
unique | 重複を除く |
unique_by(.id) | 指定キーの重複を除く |
min / max | 最小値 / 最大値 |
add | 数値の合計や配列の結合 |
any / all | 1件以上 / 全件が真か |
jq '.users | sort_by(.age) | map({name, age})' data.json
jq '.scores | {count: length, total: add, max: max}' data.json
sort や unique は結果の配列を返し、入力ファイルを並べ替えるものではありません。
オブジェクトとキー
| フィルタ | 用途 |
|---|---|
keys | キーをソートして配列で返す |
keys_unsorted | 元に近い順序でキーを返す |
has("name") | キーの有無を確認 |
to_entries | オブジェクトを {key, value} の配列へ変換 |
from_entries | {key, value} の配列をオブジェクトへ戻す |
. + {active: true} | オブジェクトを浅く結合 |
.name // "unknown" | false または null の場合に既定値 |
jq 'to_entries | map({key, value: (.value | tostring)}) | from_entries' data.json
// は false も既定値へ置き換えます。false を有効値として残す必要がある場合は条件を明示してください。
パスを扱う
jq 'path(.profile.age)' data.json
jq 'getpath(["profile", "age"])' data.json
jq 'setpath(["profile", "age"]; 19)' data.json
jq 'delpaths([["secret"], ["profile", "token"]])' data.json
path はパスを配列で返し、getpath・setpath は動的なパスを読み書きします。これらも結果を標準出力へ返すだけで、入力ファイル自体は変更しません。
値の作成と更新
jq '{id: .user.id, displayName: .user.name}' data.json
jq '. + {checked: true}' data.json
jq '.count += 1' data.json
jq '.tags += ["json"]' data.json
jq 'del(.password, .token)' data.json
| フィルタ | 用途 |
|---|---|
{name, age} | 同名キーで新しいオブジェクトを作る |
{userName: .name} | キー名を変えて作る |
[.users[].name] | 複数出力を配列へまとめる |
.field = value | 値を置き換えた結果を返す |
.field |= filter | 現在値へフィルタを適用する |
del(.field) | キーを除いた結果を返す |
jqの「代入」は、変更後のJSONを出力するフィルタです。入力ファイルへの保存は別途必要です。
型と変換
jq '.items[] | type' data.json
jq '.count | tonumber' data.json
jq '.id | tostring' data.json
jq '.name | ascii_downcase' data.json
| フィルタ | 用途 |
|---|---|
type | object、array、string などを返す |
tonumber | 数値形式の文字列を数値へ変換 |
tostring | 値を文字列表現へ変換 |
length | 配列・オブジェクト・文字列の長さ |
empty | 結果を出力しない |
型が一定でない外部データでは、変換前に type や select(type == "number") で確認します。
よく使うオプション
| オプション | 用途 |
|---|---|
-r | 文字列の引用符を外して出力 |
-c | JSONを1行で出力 |
-e | 最後の出力が false・null なら失敗終了 |
-n | 入力なしでJSONを生成 |
-s | 複数のJSON入力を1つの配列として読む |
-S | オブジェクトのキーを並べ替える |
--arg name value | 外部値を文字列として渡す |
--argjson name json | 外部値をJSONとして渡す |
シェルスクリプトで判定したい場合は -e が便利です。
if jq -e '.enabled == true' config.json > /dev/null; then
echo "enabled"
fi
外部値を安全に渡す
name="Ada"
jq --arg name "$name" '.users[] | select(.name == $name)' data.json
limit=10
jq --argjson limit "$limit" '.users[:$limit]' data.json
変数を jq の式へ直接文字列連結すると、引用符の崩れや意図しない式の実行につながります。文字列は --arg、数値・配列・オブジェクトは妥当なJSONであることを確認して --argjson を使います。
JSON Linesと出力形式
1行に1つのJSONが並ぶJSON Linesは、そのまま1件ずつ処理できます。
jq -c 'select(.level == "error")' app.jsonl
複数のJSONをまとめたい場合は -s を使います。
jq -s 'map(.duration) | add' app.jsonl
JSON文字列だけを別コマンドへ渡す場合は -r、JSONの形を保って1行ずつ渡す場合は -c を選びます。
終了コードを利用する
CIやシェルスクリプトでは、表示内容ではなく終了コードで成否を判定できます。
jq -e '.version != null' package.json > /dev/null
status=$?
echo "$status"
-e は最後の出力が false または null なら非ゼロで終了します。ただし、ファイルが読めない、JSON構文が壊れている、フィルタが失敗した場合も非ゼロになります。必要なら標準エラーを記録して原因を分けてください。
APIレスポンスを確認する
curl --fail-with-body --silent --show-error \
"https://api.example.com/users" |
jq -c '.users[] | {id, name}'
APIトークンはコマンドへ直接書くと履歴へ残ることがあります。環境変数や利用中の秘密情報管理手段を使い、デバッグ出力にも含めないでください。信頼できないURLや値は、文字列連結ではなくコマンドの引数として安全に渡します。
APIがJSON以外のエラーページを返す可能性もあります。curl --fail-with-body などでHTTPエラーを検出し、jqの失敗と区別します。
ファイル更新時の注意
次の書き方は避けてください。シェルが先に出力先を空にするため、入力データを失います。
# 実行しない
jq '.enabled = true' config.json > config.json
別ファイルへ出力し、jqが成功した場合だけ置き換えます。
tmp_file="$(mktemp)"
if jq '.enabled = true' config.json > "$tmp_file"; then
mv "$tmp_file" config.json
else
rm -f "$tmp_file"
fi
重要な設定ファイルは、更新前にバックアップと差分確認も行ってください。