jqによるJSONオブジェクトの変換と構築
map、to_entries、オブジェクト構築を使ってデータを整形し、新しいJSONペイロードを生成します。
「jqによるJSONオブジェクトの変換と構築」はCoddyKit上の無料Linux Command Line & Bash Scripting Masteryレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLinux Command Line & Bash Scripting Mastery学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。
JSON を変換する理由
API やログファイルから得られる生の JSON が、そのまま必要な形になっていることはほとんどありません。大きなオブジェクトから特定のフィールドだけを取り出したい場合や、キーの名前を変更したり、ネストされた構造をフラット化したり、別のサービスに送信するまったく新しいペイロードを作成したりする場合があります。
jq は軽量で強力なコマンドライン JSON プロセッサーです。1 つのパイプラインで、こうした変換を実行できます。このレッスンでは、データの形を組み替えるための 3 つの基本テクニックを学びます。
- オブジェクトの構築 — 新しい JSON オブジェクトを一から作成します
- map — 配列のすべての要素に変換を適用します
- to_entries / from_entries — オブジェクトのキーと値の組を配列として扱い、フィルタリングして再構築できるようにします
すべての例では、jq がインストールされていることを前提とします(apt install jq / brew install jq)。
オブジェクト構築の基本
jq の最も基本的な機能はオブジェクトの構築です。式を {} で囲むことで、新しい JSON オブジェクトを作成します。含めるフィールドと、そのフィールドの名前を指定できます。
構文:
{ newKey: .existingField }— フィールド名を変更します{ name, age }— 新しいキーがフィールド名と同じ場合の省略記法です{ total: (.price * .qty) }— 式の中で値を計算します
次のスニペットは商品 JSON を読み込み、計算した subtotal フィールドを含む、より簡潔な構造を生成します。
#!/usr/bin/env bash
# Object construction: pick and rename fields
product='{
"id": 42,
"name": "Widget Pro",
"price": 9.99,
"qty": 3,
"warehouse": "EU-West"
}'
echo "$product" | jq '{
productId: .id,
name,
subtotal: (.price * .qty)
}'ネストされたデータからのオブジェクト構築
実際の JSON は、多くの場合ネストされています。jq では、オブジェクトコンストラクター内でネストされたパスをたどり、同時に構造をフラット化できます。
コンストラクターの値の式では、ドットパス記法を使用します。
{ city: .address.city }{ lat: .location.coords.lat }
次の例では、深くネストされたユーザーレコードを、CSV のヘッダー行や API リクエストボディに適したフラットな概要へ変換します。
#!/usr/bin/env bash
user='{
"id": "u-001",
"profile": {
"displayName": "Ada Lovelace",
"contact": { "email": "ada@example.com", "phone": "+44-700" }
},
"plan": "pro"
}'
echo "$user" | jq '{
id,
name: .profile.displayName,
email: .profile.contact.email,
plan
}'map による配列の変換
map(expr) は jq における for-each に相当します。入力配列のすべての要素に expr を適用し、同じ長さの新しい配列を返します。
重要なポイント:
map(expr)は[.[] | expr]の糖衣構文です- 内部の式には、オブジェクト構築を含む任意の jq フィルターを指定できます
select()と組み合わせて、変換前にフィルタリングできます
次のスニペットは注文の一覧を処理し、出荷明細に必要なフィールドだけを残します。
#!/usr/bin/env bash
orders='[
{"orderId": 1, "customer": "Alice", "total": 42.50, "status": "shipped"},
{"orderId": 2, "customer": "Bob", "total": 18.00, "status": "pending"},
{"orderId": 3, "customer": "Carol", "total": 99.99, "status": "shipped"}
]'
# Produce a shipping manifest: only shipped orders, slim fields
echo "$orders" | jq '[
.[] | select(.status == "shipped") | {
id: .orderId,
recipient: .customer,
amount: .total
}
]'計算フィールドを使った map
map の内部では、値をコピーするだけでなく、新しい値の計算、型の変換、フィールドの結合も行えます。よく使われるパターンは次のとおりです。
- 文字列補間:
"\(.first) \(.last)" - 算術演算:
(.price * 1.2 | round)で 20% のマークアップを適用します - 条件分岐:
if .score >= 90 then "A" else "B" end
次の例では、従業員の一覧に計算した fullName と、経験年数に基づく seniority ラベルを追加して情報を拡張します。
#!/usr/bin/env bash
staff='[
{"first": "Grace", "last": "Hopper", "years": 15},
{"first": "Alan", "last": "Turing", "years": 4},
{"first": "Linus", "last": "Torvalds","years": 9}
]'
echo "$staff" | jq 'map({
fullName: "\(.first) \(.last)",
years,
seniority: (if .years >= 10 then "senior" elif .years >= 5 then "mid" else "junior" end)
})'to_entries の理解
to_entries は JSON オブジェクトを {key, value} の組の配列に変換します。これにより、オブジェクトのフィールドに対して配列操作(map、select、sort)を実行できるようになります。オブジェクトに対しては、この操作を直接行えません。
変換例:
- 入力:
{"a": 1, "b": 2} - 出力:
[{"key": "a", "value": 1}, {"key": "b", "value": 2}]
逆の操作は from_entries で、この配列をオブジェクトに戻します。これらを組み合わせた to_entries | map(...) | from_entries は、オブジェクト単位の変換で使われる慣用パターンです。
#!/usr/bin/env bash
# Demonstrate to_entries and from_entries
config='{"host": "db.local", "port": 5432, "ssl": true}'
echo "--- to_entries output ---"
echo "$config" | jq 'to_entries'
echo "--- round-trip back to object ---"
echo "$config" | jq 'to_entries | from_entries'to_entries によるキーのフィルタリング
to_entries の最も実用的な用途の 1 つは、キー名自体に基づいて保持または削除するキーを動的にフィルタリングすることです。キー名を事前に把握できない場合、オブジェクト構築ではこの操作を行えません。
パターン:
to_entries | map(select(.key | test("regex"))) | from_entriesto_entries | map(select(.key != "secret")) | from_entries
次のスニペットは、設定オブジェクトを外部サービスに転送する前に、アンダースコアで始まるすべてのキー(内部用/プライベートフィールド)を削除します。
#!/usr/bin/env bash
raw_config='{
"endpoint": "https://api.example.com",
"timeout": 30,
"_internalToken": "s3cr3t",
"_debugMode": true,
"retries": 3
}'
# Remove any key starting with underscore
echo "$raw_config" | jq '
to_entries
| map(select(.key | startswith("_") | not))
| from_entries
'to_entries によるキーの動的な名前変更
オブジェクト構築では、記述時にキー名がわかっている場合にキーの名前を変更できます。to_entries を使うと、キー名をプログラムで変更できます。たとえば、camelCase を snake_case に変換したり、プレフィックスを追加したりできます。
map の内部で各エントリの .key フィールドを更新し、その後 from_entries にパイプします。
map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase)— camelCase を snake_case に変換しますmap(.key |= "app_" + .)— すべてのキーにプレフィックスを追加します
次の例では、コンテナに注入する前に、すべての環境変数名へ APP_ を付けて名前空間を分けます。
#!/usr/bin/env bash
env_vars='{"host": "localhost", "port": "8080", "debug": "false"}'
# Add APP_ prefix and uppercase all keys
echo "$env_vars" | jq '
to_entries
| map({ key: ("APP_" + (.key | ascii_upcase)), value })
| from_entries
'with_entries:便利な省略記法
to_entries | map(...) | from_entries というパターンは非常によく使われるため、jq には省略記法として with_entries(expr) が用意されています。
動作はまったく同じですが、より簡潔に記述できます。
with_entries(.value |= . * 2)— 数値の値をすべて 2 倍にしますwith_entries(select(.value != null))— 値が null のキーを削除しますwith_entries(.key |= ascii_upcase)— すべてのキーを大文字にします
次のスニペットは、値が null または空文字列であるすべてのキーを削除します。これは REST API に PATCH リクエストを送信する前によく行うクリーンアップ処理です。
#!/usr/bin/env bash
patch_body='{
"name": "Mehmet",
"email": "",
"phone": null,
"city": "Istanbul"
}'
# Drop empty/null fields before PATCH
cleaned=$(echo "$patch_body" | jq '
with_entries(select(.value != null and .value != ""))
')
echo "Cleaned payload:"
echo "$cleaned"
# In practice you would pipe to curl:
# curl -s -X PATCH https://api.example.com/users/1 \
# -H "Content-Type: application/json" \
# -d "$cleaned"パイプラインでの map とオブジェクト構築の組み合わせ
実際の変換では、複数の jq 操作を連結します。API ペイロードを準備する一般的なパイプラインでは、次の処理を行います。
map(select(...))で入力配列をフィルタリングします- オブジェクト構築で各要素の形を組み替えます
- 計算フィールドを追加します
- 結果を並べ替えます
次の例では、サーバーメトリクスの一覧を読み込み、CPU 使用率が高いサーバーだけを残して、Webhook に POST できる簡潔なアラートペイロードを生成します。
#!/usr/bin/env bash
metrics='[
{"host": "web-01", "cpu": 23, "mem": 60, "region": "eu"},
{"host": "web-02", "cpu": 91, "mem": 88, "region": "eu"},
{"host": "db-01", "cpu": 78, "mem": 95, "region": "us"},
{"host": "db-02", "cpu": 12, "mem": 40, "region": "us"}
]'
alerts=$(echo "$metrics" | jq '[
.[] | select(.cpu > 75 or .mem > 85) | {
server: .host,
region,
severity: (if .cpu > 90 or .mem > 90 then "critical" else "warning" end),
metrics: { cpu: .cpu, mem: .mem }
}
] | sort_by(.severity)')
echo "$alerts"複数のソースから新しい JSON オブジェクトを構築する
jq では、加算演算子 + と as $var による変数束縛を使って、複数の JSON ソースから入力をマージし、オブジェクトを構築できます。
便利なパターン:
obj1 + obj2— 2 つのオブジェクトをマージします(キーが競合する場合は右辺が優先されます)--argjson— 2 つ目の JSON ドキュメントを変数として渡します$ENV— jq の内部から環境変数を直接読み取ります
次のスニペットは、基本設定に環境固有の上書き設定をマージします。これは、シェルスクリプトで 12-factor アプリケーションの設定を管理する際によく使われるパターンです。
#!/usr/bin/env bash
base_config='{
"logLevel": "info",
"timeout": 30,
"retries": 3,
"database": "postgres://db.local/app"
}'
env_overrides='{
"logLevel": "debug",
"database": "postgres://db.staging/app_staging"
}'
# Merge: overrides win on conflicts
merged=$(echo "$base_config" | jq --argjson overrides "$env_overrides" '. + $overrides')
echo "Merged config:"
echo "$merged"理解度チェック:to_entries と map
次の JSON オブジェクトがあり、値が 0 未満のキーをすべて削除して、0 以上の値だけを持つ新しいオブジェクトを作成するとします。これを正しく実行する jq 式はどれでしょうか。
入力:{"a": 10, "b": -3, "c": 0, "d": 5}
レッスンのまとめ:jq による JSON の変換
jq で JSON の形を組み替えるための基本的なテクニックを学びました。
- オブジェクト構築
{}— 入力からフィールドを選択、名前変更、計算して新しいオブジェクトを作成します map(expr)— ネストされたオブジェクト構築や、フィルタリング用のselect()を含む任意の変換を、配列のすべての要素に適用しますto_entries/from_entries— オブジェクトを{key, value}の組の配列に変換してキーと値に配列操作を適用できるようにし、その後オブジェクトに戻しますwith_entries(expr)— to_entries → map → from_entries という一連のパイプラインを簡潔に書くための省略記法です+と--argjsonによるオブジェクトのマージで、複数ソースのペイロードを扱います
これらの基本要素は組み合わせて使えます。select でフィルタリングし、オブジェクト構築で形を組み替え、計算フィールドで情報を加え、すべてを読みやすい 1 つの jq 式に連結できます。これらのパターンを習得すれば、Python や Node で専用スクリプトを書かなくても、シェルからほぼすべての JSON ペイロードを自在に扱えるようになります。
よくある質問
「jqによるJSONオブジェクトの変換と構築」レッスンは無料ですか?
はい。「jqによるJSONオブジェクトの変換と構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Linux Command Line & Bash Scripting Masteryコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。
「jqによるJSONオブジェクトの変換と構築」で何を学びますか?
map、to_entries、オブジェクト構築を使ってデータを整形し、新しいJSONペイロードを生成します。 ブラウザで直接実行するハンズオンコードでLinux Command Line & Bash Scripting Masteryを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Linux Command Line & Bash Scripting Masteryを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLinux Command Line & Bash Scripting Masteryは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「jqによるJSONオブジェクトの変換と構築」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLinux Command Line & Bash Scripting Masteryレッスンでコードを書いて実行できますか?
はい。すべてのLinux Command Line & Bash Scripting Masteryレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- jqパイプラインによるJSONのフィルタリングと選択
- jqによるJSONオブジェクトの変換と構築
- curlとjqを組み合わせたREST APIの利用
- yqによるYAML設定ファイルの編集