APIのレスポンスをターミナルで確認するとき、巨大なJSONがズラッと流れてきて目が滑る——そんな経験はないでしょうか。jq はコマンドラインでJSONを整形・加工・抽出できるツールです。パイプと組み合わせれば、シェルスクリプトの中でJSONを自在に操れます。
普段そこまで頻繁に使うわけではなくても、APIレスポンスの確認やログの調査で jq を知っているかどうかで作業効率がまるで違います。この記事では、jqの基本構文から実践的なユースケースまで、手を動かしながら学べるように紹介します。なお、インストール手順は 公式サイト を参照してください。
jqで使うサンプルJSON
この記事では、以下のJSONを使って各機能を試していきます。
{ "total": 3, "users": [ { "id": 1, "name": "Alice", "role": "admin", "active": true }, { "id": 2, "name": "Bob", "role": "editor", "active": true }, { "id": 3, "name": "Charlie", "role": "viewer", "active": false } ]}ファイルに保存しておくと、各コマンドをそのまま実行できます。
jqの基本的な使い方
JSONの整形表示(pretty-print)
最もシンプルな使い方は、JSONの整形表示です。. はjqの「アイデンティティフィルター」で、入力をそのまま出力します。
echo '{"name":"Alice","age":30}' | jq '.'{ "name": "Alice", "age": 30}APIのレスポンスをパイプで渡すだけで、読みやすく整形できます。curl との組み合わせは定番です。
curl -s https://api.example.com/users | jq '.'キーアクセス
ドット記法でオブジェクトのプロパティにアクセスできます。
cat users.json | jq '.total'3ネストしたプロパティにも、ドットをつなげてアクセスできます。
cat users.json | jq '.users[0].name'"Alice"文字列からダブルクォートを外したいときは -r(raw output)オプションを使います。
cat users.json | jq -r '.users[0].name'Alice配列操作
インデックスアクセス
配列の要素にはインデックス(0始まり)でアクセスできます。
cat users.json | jq '.users[0]'{ "id": 1, "name": "Alice", "role": "admin", "active": true}負のインデックスも使えます。[-1] で末尾の要素を取得できます。
cat users.json | jq '.users[-1].name'"Charlie"配列イテレーション
[] をインデックスなしで使うと、配列の全要素を1つずつ展開します。
cat users.json | jq '.users[].name'"Alice""Bob""Charlie"これはjq独特の概念で、1つの入力から複数の出力を生成します。後述するパイプと組み合わせると、各要素に対して処理を適用できます。
スライス
Pythonライクなスライスもサポートしています。
cat users.json | jq '.users[0:2]'[ { "id": 1, "name": "Alice", "role": "admin", "active": true }, { "id": 2, "name": "Bob", "role": "editor", "active": true }]jqのパイプ(|)で処理をつなぐ
jqの強力な機能の1つが |(パイプ)です。UNIXのパイプと同じ発想で、前のフィルターの出力を次のフィルターの入力につなげます。
cat users.json | jq '.users[] | .name'"Alice""Bob""Charlie"この例では、.users[] で配列を展開し、各要素の .name を取り出しています。パイプは何段でもつなげられます。
jqで新しいJSONオブジェクトを組み立てる
{} を使うと、必要なフィールドだけを抜き出して新しいオブジェクトを作れます。
cat users.json | jq '.users[] | {name: .name, role: .role}'{ "name": "Alice", "role": "admin" }{ "name": "Bob", "role": "editor" }{ "name": "Charlie", "role": "viewer" }結果を配列にまとめたいときは、式全体を [...] で囲みます。
cat users.json | jq '[.users[] | {name: .name, role: .role}]'jqの便利な組み込み関数
jqには多くの組み込み関数が用意されています。よく使うものを紹介します。
length
配列の要素数やオブジェクトのキー数、文字列の長さを返します。
cat users.json | jq '.users | length'3keys
オブジェクトのキー一覧を配列で返します。
cat users.json | jq '.users[0] | keys'["active", "id", "name", "role"]select
条件に合う要素だけを抽出します。配列イテレーションと組み合わせて使います。
cat users.json | jq '.users[] | select(.active == true)'{ "id": 1, "name": "Alice", "role": "admin", "active": true }{ "id": 2, "name": "Bob", "role": "editor", "active": true }条件式には and、or、not が使えます。
cat users.json | jq '.users[] | select(.role == "admin" and .active == true) | .name'"Alice"map
配列の各要素に変換を適用して、新しい配列を返します。
cat users.json | jq '.users | map(.name)'["Alice", "Bob", "Charlie"]map の中で select を組み合わせることもできます。
cat users.json | jq '.users | map(select(.active == true) | .name)'["Alice", "Bob"]sort_by / group_by
ソートやグルーピングも簡単です。
cat users.json | jq '.users | sort_by(.name)'[ { "id": 1, "name": "Alice", "role": "admin", "active": true }, { "id": 2, "name": "Bob", "role": "editor", "active": true }, { "id": 3, "name": "Charlie", "role": "viewer", "active": false }]cat users.json | jq '.users | group_by(.active)'[ [{ "id": 3, "name": "Charlie", "role": "viewer", "active": false }], [{ "id": 1, "name": "Alice", "role": "admin", "active": true }, { "id": 2, "name": "Bob", "role": "editor", "active": true }]]主な組み込み関数まとめ
| 関数 | 説明 | 例 |
|---|---|---|
length | 長さを取得 | .users | length |
keys | キー一覧 | .users[0] | keys |
select(条件) | 条件フィルタ | select(.active == true) |
map(式) | 各要素に変換を適用 | map(.name) |
sort_by(式) | ソート | sort_by(.name) |
group_by(式) | グルーピング | group_by(.role) |
unique | 重複除去 | map(.role) | unique |
flatten | ネスト配列を平坦化 | flatten |
to_entries | {key, value} 配列に変換 | to_entries |
from_entries | {key, value} 配列からオブジェクトに戻す | from_entries |
jqの実践例
APIレスポンスの加工
curl と組み合わせて、APIレスポンスから必要な情報だけを抽出するのはjqの定番の使い方です。
# GitHub APIからリポジトリ情報を取得し、名前とスター数だけ抽出curl -s https://api.github.com/users/octocat/repos | \ jq '.[] | {name: .name, stars: .stargazers_count}'# スター数が多い順にソートしてトップ5を表示curl -s https://api.github.com/users/octocat/repos | \ jq 'sort_by(.stargazers_count) | reverse | .[:5] | .[] | {name: .name, stars: .stargazers_count}'JSONL(JSON Lines)の処理
JSONL(JSON Lines)形式のファイルも、jqで処理できます。-c(compact output)を使うと、1行1レコードで出力できます。
# JSONLの各行を処理cat logs.jsonl | jq -c 'select(.level == "error")'# JSON配列 → JSONL変換cat data.json | jq -c '.[]'# JSONL → JSON配列変換cat data.jsonl | jq -s '.'-s(slurp)オプションは、複数のJSON入力をまとめて1つの配列にします。JSONLを配列として処理したいときに便利です。
CSVライクな出力
@csv や @tsv を使うと、表形式で出力できます。
cat users.json | jq -r '.users[] | [.id, .name, .role] | @csv'1,"Alice","admin"2,"Bob","editor"3,"Charlie","viewer"ヘッダー行を付けたいときは、jqの中で先頭に追加します。
cat users.json | jq -r '["id","name","role"], (.users[] | [.id, .name, .role]) | @csv'jqとJSONPathの違い・使い分け
JSONPathはJSONデータに対するクエリ言語で、jqとは異なるアプローチでデータを抽出します。当サイトでも JSONPathの使い方 を紹介しています。両者の特徴を比較してみましょう。
| 観点 | jq | JSONPath |
|---|---|---|
| 動作環境 | CLI(コマンドラインツール) | ライブラリ / ツール組み込み |
| 用途 | データの抽出 + 加工 + 変換 | データの抽出(読み取り専用) |
| パイプ | | でフィルターを連結 | なし |
| 新規オブジェクト生成 | {key: .value} で自在に構築 | 不可 |
| 再帰検索 | .. で可能 | .. で可能 |
| フィルタリング | select() で条件指定 | ?() で条件指定 |
| 集計・変換 | map, group_by, sort_by 等豊富 | なし |
| 学習コスト | やや高い(独自の言語体系) | 低い(XPath類似の直感的な構文) |
使い分けの目安として、ターミナルでJSONを加工したいときはjq、アプリケーション内でJSONの特定パスを指定して値を取り出したいときはJSONPathが適しています。jqはデータの「変換」まで担える汎用ツール、JSONPathはデータの「指定」に特化したクエリ言語と捉えると整理しやすいでしょう。
まとめ
- jqはコマンドラインでJSONを整形・抽出・加工できるツール
.keyでプロパティアクセス、[]で配列イテレーション、|でフィルターを連結selectで条件フィルタ、mapで変換、sort_byでソートなど組み込み関数が豊富curlとの組み合わせでAPIレスポンスの確認・加工に活躍する-r(raw output)、-c(compact)、-s(slurp)のオプションを覚えておくと便利- JSONPathとは役割が異なる。ターミナルでの加工にはjq、アプリ内でのパス指定にはJSONPath
- より詳しい構文は jq公式マニュアル を参照
jqってターミナルでJSON扱うなら本当に心強い味方だよね! curl で取ってきたAPIのレスポンスを | jq '.' するだけでも世界が変わるし、select や map を覚えたらもう手放せなくなるよ。あたしも最初は jq '.' だけ使ってたけど、気づいたらパイプつなげまくってた。まずは jq '.' から始めてみて!JSONのデータ加工についてもっと知りたかったら、JSONPathの記事やJSONLの記事もチェックしてみて!