下面給出一套在 Windows/Mac/Linux 通用的 Python 將 JSON 轉為 Excel(.xlsx) 的穩妥方案,兼顧嵌套結構扁平化與NDJSON(按行 JSON)支持。核心要點:先把嵌套 JSON 做扁平化,再寫入 Excel。🛠️
一鍵安裝(建議先做)
pip install -U pandas xlsxwriter
解釋:安裝/升級 pandas(數據表處理)與 xlsxwriter(Excel 寫入引擎)。這樣能夠穩定輸出 .xlsx。若你已安裝,也可直接跳過。
通用腳本:json_to_excel.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse, json, pathlib
import pandas as pd
def _flatten(obj, parent_key='', sep='.'):
"""
遞歸扁平化任意嵌套的 dict/list:
- dict:拼接上級鍵,繼續下潛
- list:若元素是 dict,則“縱向展開”為多行;否則將標量列表拼成逗號分隔字符串
"""
items = []
if isinstance(obj, dict):
for k, v in obj.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
items.extend(_flatten(v, new_key, sep))
elif isinstance(obj, list):
if all(isinstance(x, dict) for x in obj):
for d in obj:
items.extend(_flatten(d, parent_key, sep))
else:
items.append({parent_key: ','.join(map(str, obj))})
else:
items.append({parent_key: obj})
return items
def normalize_records(data):
"""
規範化為“行”列表:每個元素是扁平化後的 dict(列名為點分隔路徑)
頂層既可為 list(常見數組)也可為 dict(單對象)
"""
rows = []
if isinstance(data, list):
for rec in data:
flat = {}
for piece in _flatten(rec):
flat.update(piece)
rows.append(flat)
elif isinstance(data, dict):
flat = {}
for piece in _flatten(data):
flat.update(piece)
rows.append(flat)
else:
raise ValueError('Unsupported JSON top-level type.')
return rows
def read_json_auto(path):
"""
自動識別 JSON 或 NDJSON:
- 先嚐試逐行 loads(命中多行即視為 NDJSON)
- 否則整體 loads
"""
txt = pathlib.Path(path).read_text(encoding='utf-8')
try:
lines = [json.loads(line) for line in txt.splitlines() if line.strip()]
if len(lines) > 1:
return lines
except Exception:
pass
return json.loads(txt)
def main(in_path, out_path, sheet):
data = read_json_auto(in_path)
rows = normalize_records(data)
df = pd.DataFrame(rows)
with pd.ExcelWriter(out_path, engine='xlsxwriter') as writer:
df.to_excel(writer, index=False, sheet_name=sheet)
# 自適應列寬(按95分位粗略估計),兼顧可讀性
ws = writer.sheets[sheet]
for idx, col in enumerate(df.columns):
width = max(12, min(60, int(df[col].astype(str).map(len).quantile(0.95)) + 2))
ws.set_column(idx, idx, width)
print(f"Wrote {len(df)} rows to {out_path}")
if __name__ == "__main__":
ap = argparse.ArgumentParser(description="Convert JSON/NDJSON to Excel")
ap.add_argument("input_json", help="輸入 JSON 或 NDJSON 文件路徑")
ap.add_argument("output_xlsx", help="輸出 Excel 文件路徑,例如 result.xlsx")
ap.add_argument("--sheet", default="data", help="工作表名稱,默認 data")
args = ap.parse_args()
main(args.input_json, args.output_xlsx, args.sheet)
運行示例
python json_to_excel.py input.json output.xlsx --sheet 數據
解釋:把 input.json 轉為 output.xlsx,工作表名為“數據”。路徑可用絕對/相對,默認編碼是 utf-8。
代碼逐段解釋(關鍵邏輯)
- 安裝與導入:使用
pandas處理表格;xlsxwriter作為 Excel 寫入引擎,兼容性好。
重要:<span style="color:red">必須安裝pandas與xlsxwriter</span>,否則無法寫出.xlsx。 -
_flatten函數:遞歸把任意深度的dict/list展開成鍵路徑→值的若干片段。- 對
dict:將父鍵與子鍵用.連接(如user.name)。 - 對
list:若元素是dict,則按行展開(相當於“多行化”);若是標量列表,轉為逗號分隔字符串。
目的:<span style="color:red">解決嵌套 JSON 直寫 Excel 時列名與結構對不齊的問題</span>。
- 對
-
normalize_records:把頂層數據規範成“行列表”。- 頂層為
list:遍歷每條記錄扁平化; - 頂層為
dict:單對象也會輸出 1 行;
這樣DataFrame就能一次性接收。
- 頂層為
-
read_json_auto:自動識別 NDJSON(每行一個 JSON 對象)與普通 JSON。- 逐行
json.loads成功且>1行 → 視為 NDJSON; - 否則整體
json.loads。
重要:<span style="color:red">同時兼容 “數組 JSON”“單對象 JSON”“NDJSON”</span>。
- 逐行
- 寫出 Excel:
pd.ExcelWriter(..., engine='xlsxwriter')寫入;set_column依據 95% 字符長度估列寬,兼顧可讀性與性能。
重要:<span style="color:red">輸出為標準 .xlsx</span>,更通用、更穩。
常見數據形態與處理要點(對比表)
| 數據形態 | 例子(簡述) | 處理策略 | 結果示意 |
|---|---|---|---|
| 頂層數組 | [{"a":1},{"a":2}] |
直接扁平化→DataFrame | 每個對象一行 |
| 單對象 | {"a":1,"b":{"c":2}} |
扁平化成 a,b.c |
一行多列 |
| NDJSON | 每行一條 JSON | 逐行解析→多行 | 行數=文件行數 |
| 列表中含字典 | "items":[{"id":1},{"id":2}] |
列表縱向展開 | 生成多行 |
| 列表為標量 | "tags":["a","b"] |
逗號拼接 | 一列字符串 |
重要提示:如需對“列表展開”做更細粒度的行合併/分組,可在生成的 DataFrame 上繼續用groupby、explode等方法定製。
端到端流程(vditor/Markdown 流程圖)
實戰小貼士 ✅
- <span style="color:red">UTF-8</span> 編碼最省心;若文件含 BOM/特殊字符,建議先用編輯器轉成 UTF-8 再處理。
- 列名使用點分隔(如
order.items.price),不破壞層級信息,方便後續透視或篩選。 - 如需多個工作表:可多次
df.to_excel(..., sheet_name=...)寫入同一ExcelWriter。 - 體量很大時(>百萬行):可分塊讀取 NDJSON(分批
writer寫入),或用pyarrow/polars進一步提速。
可能的異常與解決
- UnicodeDecodeError:文件不是 UTF-8 → 先轉碼或
read_text(encoding='gbk')試讀。 - PermissionError:
output.xlsx被佔用 → 關閉已打開的 Excel。 - 列過長被截斷:已按 95 分位估列寬,仍不足可手動調整或放寬
min/max限制。
結論
這套方案的關鍵在於 <span style="color:red">“嵌套結構扁平化 + 兼容 NDJSON + 穩定寫出 .xlsx”</span>。腳本可直接落地使用,也便於二次擴展(多表、篩選、透視等)。🚀 如果你提供一段樣例 JSON,我可以按你的字段結構把扁平化策略(哪些字段展開為行、哪些保留為列)進一步細化。