动态

详情 返回 返回

python把json轉換為execl - 动态 详情

下面給出一套在 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">必須安裝 pandasxlsxwriter</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>。
  • 寫出 Excelpd.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 上繼續用 groupbyexplode 等方法定製。

端到端流程(vditor/Markdown 流程圖)

flowchart TD
A[讀取JSON/NDJSON] --> B[自動識別格式]
B --> C{是否NDJSON?}
C -->|是| D[逐行loads並收集]
C -->|否| E[整體loads]
D --> F[normalize_records 扁平化]
E --> F[normalize_records 扁平化]
F --> G[DataFrame建表]
G --> H[寫入Excel xlsxwriter]
H --> I[自適應列寬並保存 ✅]

實戰小貼士 ✅

  • <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') 試讀。
  • PermissionErroroutput.xlsx 被佔用 → 關閉已打開的 Excel。
  • 列過長被截斷:已按 95 分位估列寬,仍不足可手動調整或放寬 min/max 限制。

結論

這套方案的關鍵在於 <span style="color:red">“嵌套結構扁平化 + 兼容 NDJSON + 穩定寫出 .xlsx”</span>。腳本可直接落地使用,也便於二次擴展(多表、篩選、透視等)。🚀 如果你提供一段樣例 JSON,我可以按你的字段結構把扁平化策略(哪些字段展開為行、哪些保留為列)進一步細化。

user avatar ivictor 头像 feixi50 头像 huangxunhui 头像 lvxingdefanka 头像 chaokunyang 头像 abigmiu_6623a1b3cafc9 头像 hezuideliangmian_6858ba2ad5082 头像
点赞 7 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.