jq
JSONを加工するためのコマンドラインツール兼、純粋関数型のドメイン特化言語。作者はStephen Dolan、2012年10月の初リリース。「sed for JSON data」と自称している通り、テキストに対するsed/awkの立ち位置をJSONで担う。実装はC(初期はHaskellで書かれていたのちCへ移植された)、ライセンスはMIT。libjqというCのAPIも提供しており、他のプログラムに組み込める。 #json #cli #dsl
フィルタが値のストリームを変換する
jqの中心概念は「フィルタ」。フィルタは入力を1つ受け取り、0個以上の値を出力する。この「0個以上」がjqの言語設計の肝で、.[]が配列を要素のストリームに展開したり、select()が条件に合わない入力に対して何も出さなかったり(=フィルタリング)、emptyが常に何も出さなかったりするのが、すべて同じ規則で説明できる。
フィルタは|で繋いでパイプラインを作る。,で繋ぐと同じ入力を複数のフィルタに流して出力を連結する。
以下、手元のjq 1.7で実行して確認した例。入力はd.json:
{"people": [{"name": "a", "age": 30, "tags": ["x", "y"]},
{"name": "b", "age": 25, "tags": ["z"]}]}
$ jq -c '.people[].name' d.json
"a"
"b" # 2つの独立した出力(配列ではない)
$ jq -c '[.people[] | select(.age > 28) | .name]' d.json
["a"] # [] で囲むとストリームを配列に集める
$ jq -c '.people | map({n: .name, a: .age})' d.json
[{"n":"a","a":30},{"n":"b","a":25}]
$ jq -c '[.people[] | .tags[]]' d.json
["x","y","z"] # 二重の展開でフラット化になる
?は「エラーを握り潰す」演算子(tryの短縮形)、//は左辺がfalse/nullのときに右辺を返す代替演算子。
$ jq -c '.missing // "default"' d.json
"default"
$ jq -c '.people[0].nope?' d.json
null
reduce / foreach
ストリームを畳み込む。reduceは最終結果だけを、foreachは途中経過を各ステップ出力する。
$ jq -c 'reduce .people[].age as $x (0; . + $x)' d.json
55
$ jq -c '[foreach .people[].age as $x (0; . + $x)]' d.json
[30,55]
ユーザ定義関数はdefで書ける。再帰も書けるため、jqの言語自体はチューリング完全。
$ jq -c 'def double: . * 2; .people[0].age | double' d.json
60
パス式と更新
jqが単なる抽出ツールと一線を画すのがパス式。path()は値ではなくそこへ至る経路を返し、getpath/setpath/delpathsや更新演算子|=はこのパスの上で動く。
$ jq -c 'path(.people[0].name)' d.json
["people",0,"name"]
$ jq -c '.people[0].age |= . + 1 | .people[0]' d.json
{"name":"a","age":31,"tags":["x","y"]}
|=の左辺には「パスとして評価できる式」しか書けない、という制約があり、これがjqを学ぶうえでの最初の壁になりやすい。
その他のよく使う機能
to_entries/from_entries/with_entries— オブジェクトとキーバリュー配列の相互変換group_by/sort_by/unique_by/min_by/max_by@base64@uri@csv@tsv@html@shなどのフォーマット文字列limit(n; expr)/first(expr)/inputs— ストリームの制御と複数入力の読み込みINDEX(stream; key)/IN/JOINなどのSQLライクな演算子import/includeによるモジュールシステム--stream— 巨大なJSONを[パス, 値]のイベント列としてストリーミング処理する(全体をメモリに載せない)
$ echo '{"a":[1,2]}' | jq -c --stream '.'
[["a",0],1]
[["a",1],2]
[["a",1]]
[["a"]]
数値の扱い
jqの数値はIEEE754倍精度が基本。1.7以降、変更されないリテラルはそのままの表記が保存されるが、演算を挟むと精度が落ちる。
$ echo '{"n": 10000000000000000001}' | jq '.n'
10000000000000000001 # リテラルはそのまま
$ echo '{"n": 10000000000000000001}' | jq '.n + 0'
1e+19 # 演算すると倍精度になる
1.8.0でdecimal number literalによる精度保持が入っている。任意精度整数演算そのものを求めるならgojqを使う手がある。
メンテナンスの歴史
jqは長い停滞期間を経験している。既存メンテナが力尽きて反応しなくなった一方、個人アカウント配下のリポジトリだったためメンテナを追加する手段がなく、身動きが取れない状態が続いた。この状況を解消するためにjqlang GitHub Organizationが作られ、Stephen Dolanがリポジトリを移管した。
- 1.7 (2023-09-06) — 5年ぶりのリリース。新organization・新メンテナ体制での最初のリリース。GitHub ActionsによるCI/CD整備、
JQ_COLORSによる色設定など - 1.7.1 (2023-12-13) — ヒープバッファオーバーフローなどのセキュリティ修正
- 1.8.0 (2025-06-01) — decimal number literal、
trim/ltrim/rtrim、@uridフォーマットなど。バージョン番号体系を1.X.Yのセマンティックバージョニングへ変更 - 1.8.1 (2025-07-01) — 1.8.0で見つかったセキュリティ・性能・ビルドの問題の修正
- 1.8.2 (2026-06-20) — 16件のセキュリティ脆弱性修正。Windows arm64やDocker arm/v7のビルド追加
別実装
jqの言語は複数の再実装を生んでいる。
JSONクエリ言語の中での位置づけ
JMESPathがSDK組み込み用に表現力を絞った「仕様先行」の言語であるのに対し、jqは表現力を優先した単体の処理系。算術・正規表現・再帰・ユーザ定義関数・ストリーミングまで揃っており、手元でJSONを自由にこねる用途では圧倒的に強い。反面、公式の言語仕様書は存在せず、事実上jq本体の実装が仕様になっている。