Skip to content
ブログに戻る
チュートリアル

ネスト JSON を CSV に平坦化:5 つの戦略と選択マトリクス

今すぐネスト JSON を CSV に平坦化しよう:5 戦略 — ドット記法、インデックス配列、行展開、Stringify。Excel、Pandas、BigQuery、Postgres 向けの選択マトリクスを解説。

12 分で読める

ネスト JSON を CSV に平坦化する方法:5 つの戦略と選択マトリクス

幾何学的な問題

毎回同じ壁にぶつかる。API はネストした JSON を返してくるのに、Slack のアナリストはただスプレッドシートが欲しいだけ。mongoexport$oid ラッパーと 3 階層のメタデータを吐き出し、BigQuery はフラットなテーブルを要求してくる。ネスト JSON を CSV に平坦化するのは構文の問題ではない。幾何学的な問題だ。JSON は木構造、CSV はグリッド。枝をどう畳むかを決めずに、木をグリッドへ移すことはできない。

畳み方の戦略は、ちょうど 5 つある。誤ったものを選べば、200 列の Excel を渡してしまったり、Twitter ID の精度を失ったり、パイプラインが依存する往復変換を壊したりする。正しいものを選べば、変換はワンライナーで済む。

戦略ワンライナー適した用途
ドット記法customer.address.cityExcel/Sheets の分析
アンダースコアcustomer_address_citySQL に親和的な列名
インデックス配列items.0.sku, items.1.sku固定長配列
行展開子要素ごとに親を反復Pandas/BigQuery 分析
Stringify単一セルに "{\"city\":\"Seattle\"}"可逆な往復変換

以下では 5 戦略を順に見て、コンシューマ別(Excel、Pandas、BigQuery、Postgres)の選択マトリクスを示し、最適戦略が一見では分かりにくい実ペイロードを 4 件取り上げる。双方向変換の総合的な概要(パーサーライブラリ、ストリーミング、エンコーディングの罠)については、CSV ↔ JSON 変換ガイドを参照してほしい。

なぜネスト JSON は CSV に収まらないのか

JSON は CSV に存在しない 3 種類の構造を運ぶ。階層はオブジェクトの中のオブジェクト。シーケンスは配列。混在はその組み合わせ:オブジェクトの配列、配列を持つオブジェクト、配列の配列。典型的な EC サイトの注文は、その 3 つすべてを同時に含む。

CSV はちょうど 2 次元しか持たない:行と列。「この列が 3 つの子を保持する」ための第 3 の軸は存在しない。木からグリッドを要求するなら、何かを犠牲にしなければならない。子要素を複数の列に広げる(items.0.options.0.value のような名前と共存する)、複数の行に広げる(親フィールドが反復する)、あるいはテキストとして 1 セルに押し込み、もはや構造として扱わない。

以下の各戦略は、それぞれ異なる答えを返す。可読性を保ち往復安全性を失うものもあれば、その逆もある。万能なものはない。次にファイルを読む相手に合わせて答えを選ぶ。

5 つの平坦化戦略の比較

戦略 1:ドット記法(customer.address.city

ドット記法はルートからリーフへ辿り、. でキーを連結する。ネストしたオブジェクトはリーフごとに 1 列となり、パスが列名にエンコードされる。

{ "customer": { "address": { "city": "Seattle" } }, "email": "alice@example.com" }

は以下のようになる。

customer.address.city,email
Seattle,alice@example.com

Pandas なら 1 行で完結する:

import pandas as pd

data = [{"customer": {"address": {"city": "Seattle"}}, "email": "alice@example.com"}]
df = pd.json_normalize(data, sep='.')
df.to_csv("out.csv", index=False)

JavaScript なら、小さな再帰関数で十分だ:

function flattenDot(obj, prefix = '', acc = {}) {
  for (const [k, v] of Object.entries(obj)) {
    const key = prefix ? `${prefix}.${k}` : k;
    if (v && typeof v === 'object' && !Array.isArray(v)) {
      flattenDot(v, key, acc);
    } else {
      acc[key] = v;
    }
  }
  return acc;
}

**長所:**人間が読みやすい、Pandas のデフォルト、元のパスを保持。**短所:**列名が長くなりがち(Kubernetes のスペックは spec.template.spec.containers.0.resources.limits.memory のような名前を生む)、実際のキーに . が含まれる場合(Google Analytics 4 のイベントパラメータがそうだ)にドットが曖昧になる。

戦略 2:アンダースコア記法(customer_address_city

考え方は同じで、区切り文字が違うだけ。._ に置き換えれば、結果は SQL セーフになる:SELECT customer_address_city FROM events は識別子を引用符で囲まずに動く。BigQuery、Snowflake、Postgres はいずれもこちらを好む。

import pandas as pd
df = pd.json_normalize(data, sep='_')

ドットとアンダースコアの選択は、純粋に下流のツール次第だ。Excel のアナリストはドットを自然に読む;SQL エンジンは文句を言わずアンダースコアを受け入れる。引数を 1 つ変えれば切り替わる。

**長所:**SQL セーフな列名、BigQuery 準拠の識別子、引用符不要。**短所:**キーに _ が含まれる場合(. よりは少ないが、なくはない)には曖昧さが残る。

戦略 3:インデックス配列(items.0.sku, items.1.sku

オブジェクトはキーが一意なので、きれいに平坦化できる。配列は長さに上限がないので、そうはいかない。インデックス戦略は配列位置をパスのセグメントとして扱う:items[0]items.0 になる。

{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }

は以下のようになる。

id,items.0.sku,items.1.sku
ord-001,A,B

これが JSON to CSV コンバータ の Flatten のデフォルト挙動だ。各リーフが独自の列を持ち、位置は名前に記録される。

**長所:**すべての値が独自のセルを持つ、位置が保たれる、行の重複がない。**短所:**列数が爆発する(100 アイテム= 100 列)、配列長が異なる行は不揃いなテーブルを生む、下流の集計が壊れる(SUM(items.*.qty) ができない)。

戦略 4:行展開(配列を複数行へ)

配列に合わせてテーブルを横に広げるのではなく、縦に伸ばす。配列要素 1 つにつき親フィールドを 1 回ずつ反復し、各要素を独自の行にする。

{ "order_id": "ord-001", "customer": "Alice", "items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}] }

は以下のようになる。

order_id,customer,items.sku,items.qty
ord-001,Alice,A,2
ord-001,Alice,B,1

Pandas なら 1 行で展開と正規化の両方ができる:

import pandas as pd

orders = [{"order_id": "ord-001", "customer": "Alice",
           "items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}]}]
df = pd.json_normalize(orders, record_path='items', meta=['order_id', 'customer'])
df.to_csv("orders.csv", index=False)

SQL なら、UNNEST が同じ役割を果たす:

SELECT order_id, item.sku, item.qty FROM orders, UNNEST(items) AS item;

**長所:**Pandas と BigQuery がこの形をネイティブに扱う、集計が機能する(GROUP BY order_id)、スキーマがスリムに保たれる。**短所:**親フィールドがすべての子行に重複する(ストレージが膨張する)、1 対多の境界が暗黙的(order_id が必要)、同レベルに 2 つの配列があると、慎重に UNNEST しない限りデカルト積になる。

戦略 5:Stringify(セル内 JSON)

過激な選択肢:そもそも平坦化しない。ネストした値全体を JSON 文字列としてシリアライズし、単一セルに入れる。外側のテーブルはフラットなまま、構造は内部に逐語的に保たれる。

{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }

は以下のようになる。

id,items
ord-001,"[{""sku"":""A""},{""sku"":""B""}]"

これが JSON to CSV コンバータ の Stringify モードだ。列数が爆発することはなく、元の形がバイト単位で保たれ、逆変換は入力を厳密に再構築する。

**長所:**100% 可逆、列数が予測可能、逆変換時の Infer types と組み合わせれば往復安全。**短所:**Excel ユーザにはエスケープされた引用符が見える、SQL エンジンは値を問い合わせるのに JSON 関数が必要(BigQuery では JSON_EXTRACT_SCALAR、Postgres では ->>'key')、スプレッドシートの関数式はセル内部に手が届かない。

5 戦略の横並び比較

同じ入力を 5 戦略すべてで処理:{"id":"ord-001","customer":{"name":"Alice"},"items":[{"sku":"A","qty":2},{"sku":"B","qty":1}]}

戦略列数往復安全最適なコンシューマ
ドット記法配列に伴い増加不可Excel のアナリスト
アンダースコア配列に伴い増加不可SQL ウェアハウス
インデックス配列配列スロットごとに 2 列不可(逆変換で曖昧)固定長配列
行展開スリム、子ごとに 1 行部分的(キーが必要)Pandas/BigQuery
Stringify固定パイプラインの往復

選択マトリクス:コンシューマ別の推奨戦略

まずコンシューマを引き、対応する推奨戦略を読み取る。

コンシューマ推奨戦略理由
Excel/Sheets(アナリスト)ドット + 大きい配列は Stringify読みやすい列名;大きな配列でもシートが爆発しない
Excel-EU(DE/FR/IT/ES)ドット + ; 区切り + UTF-8 BOMセミコロン必須;BOM で文字化け防止
Pandas(json_normalizeexplodeアンダースコア + 行展開SQL 親和的な列;展開は groupby と相性が良い
BigQuery/SnowflakeTSV + Stringify か行展開タブは引用符の罠を回避;JSON_EXTRACT でセル内を問い合わせ
PostgreSQL COPYRFC 4180 + アンダースコア + フラットSQL セーフな列;厳格な RFC 引用
MongoDB → BigQuery ETLNDJSON を直接ロード、CSV はスキップBigQuery は NDJSON をネイティブにロード;CSV は遠回り

Excel/Google Sheets:ロケールの罠

Excel の列名に実用的な長さ制限はない。本当の罠は 3 つある。

第 1 に、ロケールの分断。ヨーロッパの Excel(ドイツ、フランス、イタリア、スペイン)は , が小数点なので、区切り文字に ; を期待する。カンマ区切りの CSV を開くと、すべての行が A 列に潰れて入る。json-to-csv ツールの Excel プリセットは、ワンクリックで ; + CRLF + UTF-8 BOM へ切り替わる。

第 2 に、指数表記。Excel は 90071992547409939.00719925474E+15 として表示する。大きな整数は元の JSON で文字列として保持し、BOM を有効化して Excel にセルをテキスト扱いさせる。コンバータ側で大きな整数は自動検出している。

第 3 に、実用的な列数の限界。Excel は理論上 16,384 列をサポートするが、500 列を超えると扱いきれなくなる。重いサブツリーを Stringify するか、変換前に jq で射影しておく。

Pandas:json_normalizeexplode

ネストした配列に対する標準パターンは、record_pathmeta を 1 パスで使うことだ:

import pandas as pd

orders = [{
    "order_id": "ord-001",
    "customer": {"name": "Alice", "city": "Seattle"},
    "items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}]
}]

df = pd.json_normalize(orders, record_path='items',
    meta=['order_id', ['customer', 'name'], ['customer', 'city']], sep='_')
df.to_csv("orders.csv", index=False)

出力はアイテムごとに 1 行で、order_idcustomer_namecustomer_city が反復される。これは先に explode を実行してから json_normalize するより優れる:record_path は中間のオブジェクト列をスキップし、meta でどの親フィールドを伝播させるか制御できる。配列要素がさらにネストしたオブジェクトを含む入力では、max_level= で深さに上限を設ける。

BigQuery/Snowflake:TSV + セル内 JSON

BigQuery の LOAD DATA は CSV の引用に厳格で、引用テキスト内にカンマがあるファイルをしばしば誤解釈する。テキストフィールド内にタブがほぼ現れないため、TSV のほうが安全だ:

bq load --source_format=CSV --field_delimiter='\t' \
  dataset.orders gs://bucket/orders.tsv \
  order_id:STRING,customer:STRING,items:STRING

ネストデータを単一列の Stringified JSON としてロードしても、BigQuery は JSON_EXTRACT_SCALAR でその中を問い合わせられる:

SELECT order_id, JSON_EXTRACT_SCALAR(items, '$[0].sku') AS first_sku
FROM dataset.orders;

Snowflake は VARIANT で同等の機能を提供し、items:0.sku::STRING のようなパスクエリを書ける。両方のエンジンで、ネストした配列が大きいか可変長の場合、完全な平坦化よりも Stringify + JSON パスクエリのほうが優れる。

PostgreSQL COPY:RFC 4180 厳格

COPY ... FROM ... WITH (FORMAT csv, HEADER true) は、現場で出会う中で最も厳格な RFC 4180 リーダーだ。2 つの挙動が人を躓かせる。

第 1 に、COPY は UTF-8 BOM を受け付けない。バイト順マークが最初の列名のリテラル接頭辞になり(id ではなく id)、id を参照するクエリはすべて静かに失敗する。Postgres を対象とする場合は BOM を切る。

第 2 に、COPY はネストデータをネイティブにはパースできない。ロード前に配列を複数行へ展開するか、宛先を jsonb として定義し、ネストした値を Stringify する:

CREATE TABLE orders (order_id text PRIMARY KEY, customer text, items jsonb);
COPY orders FROM '/tmp/orders.csv' WITH (FORMAT csv, HEADER true);
SELECT order_id, items->0->>'sku' AS first_sku FROM orders;

エンドツーエンドで JSON を喋るパイプラインなら、CSV をスキップして、代わりに JSON 行入力で COPY ... FROM ... WITH (FORMAT text) を使う。

実世界のペイロード解説

解説 1:EC サイトの注文(顧客 + items 配列)

典型的な注文は、ネストした顧客情報と可変長の items 配列を組み合わせる:

[{ "id": "ord-001",
   "customer": { "name": "Alice", "address": {"city": "Seattle", "country": "US"} },
   "items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}] }]

正しい戦略は、ファイルを読む相手次第だ。財務部門は SKU ごとの売上を計算したいので、1 アイテム 1 行が欲しい。それが行展開戦略で、idcustomer.name を反復する 2 行を生む。オペレーション部門はフルフィルメントのダッシュボード用に 1 注文 1 行が欲しい。それがドット記法 + items を Stringify するパターンで、配列が列数を爆発させない。同じ入力で 2 つの出力、どちらもそれぞれのコンシューマには正しい。

手元で試したいなら、ペイロードを JSON to CSV コンバータに貼り付け、Nested オプションで Flatten と Stringify を切り替えてみる。「Nested E-commerce Orders」の例が同じ形をロードする。

解説 2:GitHub Issues API(labels 配列 + user オブジェクト)

/repos/{owner}/{repo}/issues エンドポイントは、混在したネスト構造を返す:

[{ "id": 1001, "title": "Bug: login 404", "state": "open",
   "labels": ["bug", "priority:high"], "user": {"login": "alice"} }]

user は有用なフィールドが 1 つだけのオブジェクト;labels は長さに上限のない文字列配列。実用的な平坦化はハイブリッドだ:user にはドット記法(user.login だけが必要)、labels には ; で区切って単一セルへインラインで結合する:

id,title,state,labels,user.login
1001,Bug: login 404,open,bug;priority:high,alice

「配列をセルに結合する」と「オブジェクトをドットで平坦化する」の両方を、1 つの戦略では捉えられない。オブジェクトの平坦化はコンバータが自動で処理するので、labels の側を jqmap(.labels = (.labels | join(";"))))で前処理するか、デフォルトの配列 Stringify 挙動を受け入れることになる。

解説 3:MongoDB の mongoexport($oid + メタデータ)

mongoexport --jsonArray は Extended JSON のラッパーを吐き出す:

[{ "_id": {"$oid": "6634a1b2c3d4e5f600000001"},
   "email": "alice@example.com",
   "metadata": { "signupDate": "2026-01-15T10:30:00Z",
                 "preferences": {"newsletter": true, "theme": "dark"} } }]

$oid ラッパーは、文字通り _id.$oid という名前の列を生み、ほとんどの SQL エンジンは拒否する。jq で前処理してアンラップする:

mongoexport --collection=users --jsonArray | jq 'map(._id = ._id."$oid")' > users.json

深くネストした metadata.preferences ブロックについては、コンシューマで選ぶ。アナリスト用のエクスポート:全部をドット平坦化する;metadata.preferences.theme はきれいに読める。パイプラインの往復:構造を保つために metadata を Stringify する。CSV パイプラインと組み合わせる完全な jq パターンについては、jq コマンドラインチートシートを参照してほしい。

解説 4:Kubernetes Pod Spec(深いネスト)

kubectl get pod -o json のレスポンスは、フラット戦略にとって最悪のケースだ。構造は日常的に 6 階層の深さに達する(spec.template.spec.containers.0.resources.limits.memory)。素朴なドット平坦化は、70 文字超の列名と 200 列以上の出力を生む。2 つの戦略が有効だ。

**kubectl jsonpath で前射影する。**実際に必要なフィールドだけを選び出す:

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\t"}{.status.phase}{"\n"}{end}' > pods.tsv

spec を Stringify し、metadata を平坦化する。metadata(name、namespace、labels)はフラットに保ち、spec は単一セルへ Stringify する:

kubectl get pods -o json | jq 'map({name: .metadata.name, namespace: .metadata.namespace, spec: (.spec | tostring)})'

そしてコンバータに Flatten モードで貼り付ける。spec 列は 1 つの JSON セルになり、metadata 列は読める状態を保つ。前射影なしで kubectl get pod -o json | json-to-csv flatten を実行するアンチパターンは避ける。列数が手に負えなくなる。

往復安全:Flatten は不可逆、Stringify は可逆

他のガイドが省きがちな前提を先に置いておく。**ドット記法、アンダースコア記法、インデックス配列、行展開はすべて、一方向の射影だ。**いずれかで平坦化すれば、CSV だけから元の JSON を完全に再構築することはできない。

反例は容易に構成できる。customer.address.city という列名は、{"customer": {"address": {"city": "..."}}}{"customer": {"address.city": "..."}} のあいだで曖昧だ。インデックス配列は可逆に見えるが、CSV は items.0.sku を配列に戻すべきか、数値キーを持つオブジェクトに戻すべきかを述べられない。行展開はグループ化キーを必要とする;order_id がなければ、どの行が同じ親に属していたか分からない。

往復を生き延びるのは Stringify だけだ。ネストした値は JSON 文字列として逐語的に保たれるので、逆コンバータはセルを読み、パースし、元のまま再挿入する。Stringify で変換し、CSV を保存し、CSV to JSON コンバータに貼り付け、Infer types を有効にすれば、入力と同一のバイト列が得られる。

実用上のルール:パイプラインの往復 → Stringify。一回限りの分析やレポート → コンシューマに応じてドット、アンダースコア、行展開。

ブラウザツールでの実行

JSON to CSV コンバータは、5 戦略のうち 2 つを直接公開している:Flatten(ドット記法とインデックス配列を組み合わせる)と Stringify(セル内に構造を保つ)。他の 3 つ(アンダースコア、行展開、SQL ターゲットプリセット)は、前処理を 1 ステップ挟めば実現できる。

典型的なセッションはクリック 5 回で済む:

  1. 構文エラーが静かな変換失敗にならないよう、JSON フォーマッタで入力を検証する。
  2. JSON を JSON to CSV コンバータに貼り付ける。変換は即座に実行される。
  3. Nested を Flatten に設定してドット + インデックスキーを得るか、Stringify にして配列とオブジェクトを単一セルに保つ。
  4. プリセットを選ぶ:パイプラインには RFC 4180、EU のスプレッドシートには Excel、ウェアハウスには TSV、カンマの多いテキストには Pipe。
  5. Swap direction をクリックし、Infer types を有効にした CSV to JSON コンバータで Stringify の往復を検証する。

すべてはブラウザ内で動く。PII、社内エクスポート、本番環境のシークレットがページを離れることはない;ページロード後のネットワークリクエストはゼロ。サードパーティのサイトへのアップロードが選択肢にない機微なデータでも安全に扱える。

よくある落とし穴

6 つの失敗モードが繰り返し現れる。

  1. **列名の爆発。**Kubernetes のスペックや GitHub PR のレビュースレッドは、数百のリーフパスを生む。対処:jqkubectl jsonpath で前射影するか、metadata を平坦化しつつ重いサブツリーを Stringify する。
  2. **配列長の不一致。**行 1 には 3 アイテム、行 2 には 5 アイテム。インデックス配列は行 1 の items.3.skuitems.4.sku に空セルを生む。対処:行展開に切り替える。
  3. **逆変換でインデックスキーが文字列扱いされる。**CSV-to-JSON が items.0.sku を見たとき、0 は厳密には文字列キーだ。一部の逆コンバータは [{"sku": "A"}] ではなく {"0": {"sku": "A"}} を再構築する。対処:往復には Stringify を使う。
  4. **キー自体に区切り文字が含まれる。**GA4 のイベントには event_params.key のように文字通りのドットを含むキーがあり、. での平坦化は曖昧なパスを生む。対処:アンダースコアを使うか、問題のキーをリネームする。拡張キーをサポートする JSON フォーマットの背景は、JSON5 と JSONC フォーマットガイドを参照してほしい。
  5. **階層ごとに型が異なる。**ある行では address がオブジェクトで、別の行では null。平坦化は null オブジェクトの箇所に空セルを生む。コンバータの schema notes 警告がこれをフラグするので、下流のコンシューマで検証できる。
  6. Excel に大きな整数が切り詰められる。$oid の Long、Twitter のスノーフレーク ID、K8s の resourceVersion は JavaScript の安全範囲(2^53 − 1)を超え、静かに丸められる。Excel はそれらを 9.00719925474E+15 として表示する。対処:元の JSON で ID を文字列として保持し、BOM を有効化し、Excel プリセットを使う。

FAQ

ネスト JSON を CSV に平坦化する最良の方法は?

ネスト JSON を CSV に平坦化する最良の方法は、下流のコンシューマ次第だ。Excel や Google Sheets にはドット記法を使う。Pandas や BigQuery でデータを集計する場合は行展開を使う。データ損失なしで CSV を JSON に戻す必要がある場合は Stringify を使う。次に読む相手に戦略を合わせる。

JSON 配列を複数の CSV 行に変換するには?

JSON 配列を複数の CSV 行に変換するには、行展開戦略を使う:配列要素 1 つにつき親フィールドを 1 回ずつ重複させ、それぞれを独自の行にする。Pandas では pd.json_normalize(data, record_path='items', meta=['order_id']) が 1 回の呼び出しでこれを行う。SQL では UNNEST(items) が同じ形を生む。親キーは展開された行をまたいで反復する。

CSV を元のネスト JSON に往復させられるか?

CSV を元のネスト JSON に往復させられるのは Stringify モードだけだ。ドット記法、アンダースコア、インデックス配列、行展開は不可逆な一方向の射影で、逆コンバータは木を完全には再構築できない。Stringify は配列とオブジェクトを単一セル内の JSON として保つので、Infer types が有効なら完全な往復はバイト単位で同一だ。

Excel で平坦化した JSON が 1 つの長い列になるのはなぜか?

Excel で平坦化した JSON が 1 つの長い列になるのは、, が小数点に予約され、Excel が区切り文字としてセミコロンを期待するヨーロッパのロケール(ドイツ、フランス、イタリア、スペイン)にいるからだ。json-to-csv の Excel プリセットは、ワンクリックで ; + CRLF + UTF-8 BOM へ切り替わる。

列名にはドット記法とアンダースコアのどちらを使うべきか?

ターゲットが Excel、Google Sheets、Pandas ならドット記法を使う;ドットは json_normalize のデフォルトで自然に読める。ターゲットが SQL ならアンダースコアを使う:Postgres、BigQuery、Snowflake はドットを含む識別子に引用符を要求するが、アンダースコアはどこでも引用符なしで受け入れられる。

pandas の json_normalize はオブジェクトの配列をどう扱うか?

Pandas の json_normalize はオブジェクトの配列を record_pathmeta 引数で扱う。pd.json_normalize(data, record_path='items', meta=['order_id'])items を要素ごとに 1 行へ展開し、order_id を反復する。配列を含まないネストオブジェクトには、より単純な pd.json_normalize(data, sep='_')customer_address_city のようなアンダースコア区切りの列名を生む。深い木では max_level= で深さを制限する。

深くネストした JSON を平坦化したときの列数の上限は?

深くネストした JSON を平坦化したときの列数の上限は Excel で 16,384、CSV 自体では事実上無制限だが、500 列を超えると出力は扱いきれなくなる。Kubernetes の Pod スペックや GraphQL のレスポンスは容易にこれを超える。JSON to CSV コンバータで重いサブツリーを Stringify するか、jqkubectl jsonpath で前射影する。

CSV 変換の前段で JSON を平坦化するのに jq は良いツールか?

はい、jq は CSV 変換の前段で JSON を平坦化するのに最適なツールだ。前射影(map({id, name}))、前展開(.[] | {id, item: .items[]})、形状の正規化を 1 行で扱える。jq パイプラインは CSV ステップの前に実行され、どのフィールドをコンバータへ渡すかを正確に制御できる。パターンは jq コマンドラインチートシートにまとめてある。

まとめ

5 つのポイント:

  1. JSON-to-CSV は構文の問題ではなく、幾何学的な問題だ。木は枝の畳み方を選ばずにグリッドへ収まらない。
  2. 5 戦略(ドット、アンダースコア、インデックス配列、行展開、Stringify)が実用的な世界を覆う。コンシューマで選ぶ。
  3. 可逆な経路は Stringify だけだ。パイプラインの往復に使う。
  4. Excel-EU と BigQuery のプリセットには理由がある。使う。
  5. 実ペイロード(mongoexport、Kubernetes スペック、GitHub レスポンス)は、たいてい jqkubectl jsonpath の前射影ステップを先に挟む必要がある。

自分のペイロードを JSON to CSV コンバータで試してみよう。ローカルで動き、5 戦略すべてを扱い、Stringify で可逆に往復する。アップロード不要、サインアップ不要、データがページを離れることはない。