JSON 轉 CSV:攤平巢狀資料
如何將巢狀 JSON 轉成扁平 CSV 列——點分鍵、陣列處理、跳脫、編碼。含實際範例與資訊損失的因應策略。
CSV 是資料分析工具的通用貨幣——Excel、Google Sheets、所有資料庫匯入、 所有 BI 工具。JSON 則是樹狀結構。兩者之間的轉換不是 1 對 1:攤平的 過程會做出抉擇、會損失資訊。本文整理你必須明確做的選擇,免得在下游 給自己驚喜。
為何 CSV 需要扁平列
CSV 是 2D 格式:一列 header 加 N 列資料,欄位數固定。JSON 是 N 維—— 物件巢狀、陣列巢狀於物件、物件巢狀於陣列。任何轉換都需要把樹 投影 成表格。
三個動作完成投影:
- 選定「列實體」——通常是頂層陣列的元素。
- 將巢狀物件以點分路徑攤平成欄位。
- 決定如何處理巢狀陣列——展開(explode)、串接(join)、或索引(index)。
物件陣列對應到列
最簡單的情況。JSON 是扁平陣列、每個元素也扁平:
[
{ "id": 1, "name": "Ada", "active": true },
{ "id": 2, "name": "Alan", "active": false }
]
每個鍵成為一欄、每個元素成為一列:
id,name,active
1,Ada,true
2,Alan,false
header 是所有元素鍵的 聯集。若某列沒有某鍵,該格留空。
攤平巢狀物件(點分鍵)
巢一層、加一個點:
[
{
"id": 1,
"name": "Ada",
"address": { "city": "London", "zip": "SW1A 2AA" }
}
]
id,name,address.city,address.zip
1,Ada,London,SW1A 2AA
多層繼續點下去:address.country.code。這套表示法與
JSONPath 一致,欄名能直接看出
來源。有的工具用 address_city(底線)或 address__city(雙底線),
擇一並寫進文件即可。
紀錄內的陣列
轉換在此變得有意見。三種合理策略,各自有不同的資訊損失:
策略 A:展開(explode)。 一個陣列元素一列。當陣列元素才是真正 的紀錄時最適合:
[
{ "id": 1, "tags": ["admin", "founder"] }
]
id,tag
1,admin
1,founder
這就是 jq 用 [.id, .tags[]] | @csv 做的事,也是 SQL 的 UNNEST。
兩個缺點——你失去原本「一列一使用者」的結構,且若紀錄有多個陣列,
你得展開笛卡爾乘積或擇一展開。
策略 B:串接(join)。 將陣列編成單一定界字串:
id,tags
1,"admin;founder"
適合短陣列、且消費端能再切分。請選用值內不會出現的定界字元, 通常是分號或豎線。
策略 C:索引(index)。 每個陣列位置一欄:
id,tags.0,tags.1
1,admin,founder
適合固定短長度且位置有意義(如 RGB 三元組)。長度可變時會崩——
最後 tags.0 到 tags.99 大半空著。
沒有萬用解。請依消費端用途選擇。
Header、定界、跳脫、編碼
四個在生產環境會咬人的 CSV 變數:
- 定界字元。RFC 4180 規定逗號,歐洲 Excel 用分號,TSV 用 tab。請在你的轉換器明確設定並寫進文件。
- 跳脫與引號。值若含定界字元、換行或雙引號,必須加引號。引號字元是
",引號內的"以雙寫處理:"。所以she said "hi"變成"she said ""hi"""。 - Header。RFC 4180 中是可選,但你應該永遠輸出。沒有 header 的轉換對下游是黑盒。
- 編碼。UTF-8 是唯一安全答案。Windows 版 Excel 雙擊
.csv仍會用區域 8-bit 編碼——在檔頭加 UTF-8 BOM(EF BB BF)能讓 Excel 自動辨識 UTF-8。沒錯,這正是 JSON 語法錯誤 告訴你要在 JSON 避免的 BOM;CSV 對它友善。
有損轉換與緩解
會丟資訊的轉換:
- 型別流失——CSV 沒有型別。
"true"、true、1都會變成字串true。請固定約定:數字用十進位、布林用true/false或1/0、日期用 ISO 8601。 - null vs 空字串——CSV 沒有
null。多數工具用空字串代替。若需區分「缺值」與「空字串」,請用不同編碼(例如 PostgreSQLCOPY的\N)。 - 巢狀陣列順序——展開時每列內部順序保留,但消費端不一定能追回父紀錄,除非你帶一欄 id。
- 陣列內物件身份——展開含物件的陣列會讓欄位倍增:
orders[*].id、orders[*].total需要加索引後綴或改成多列展開。
緩解方式都一樣:寫下轉換約定,並當作資料合約的一部分。
處理大型輸入
若 JSON 很大,不要整批載入再轉。請參考 處理大型 JSON 檔案 的串流模式——串流 JSON 解析器接到串流 CSV writer,可在常數記憶體 下處理任意大小的輸入。
動手轉
把 JSON 貼進 /zh-Hant/json/convert/csv—— 提供策略 A、B、C 處理巢狀陣列、可選定界字元、可切換 UTF-8 BOM 以 配合 Excel。全部在瀏覽器內執行,資料不會離開你的裝置。
延伸閱讀
- 處理大型 JSON 檔案——巨型輸入的串流轉換。
- JSON、YAML 與 XML 比較——上游選對格式減少轉換需求。