JSON 转 Excel:四种办法与它们各自的失真点
结论:嵌套结构、字段不一致、数组套数组,是 JSON 转表格最容易翻车的三处。四种办法按「几分钟出结果」排序,每个都标清楚会丢什么。

结论:扁平对象数组与对象包数组直接用在线工具最快,需要每周刷新就上 Power Query,字段多要清洗用 Python + pandas,要接进流水线再写 Node 脚本;动手前一旦发现嵌套或键不一致,先定清楚「一行代表什么」。
转换本身不难,难的是「转完之后发现数字变成文本、多层嵌套只剩一层」。选方法之前先看清数据结构,能省掉一次返工。
一、先判断你的 JSON 属于哪一类
打开文件看最外层:
| 结构 | 样子 | 转换难度 |
|---|---|---|
| 扁平对象数组 | [{"a":1,"b":2},{...}] |
最容易,一行一条记录 |
| 对象包数组 | {"data":[{...}],"total":100} |
容易,取 data 那一层 |
| 嵌套对象 | {"user":{"name":"x"}} |
中等,要决定展开还是拼字符串 |
| 数组套数组 | {"tags":["a","b"]} |
麻烦,一行装不下,得拆表 |
| 键不一致 | 每条记录的字段不同 | 麻烦,列会大面积空值 |
前两类直接转,成功率接近 100%;后三类先想清楚「一行代表什么」,否则转出来的表没法用。
二、方法一:在线工具(1 分钟)
打开 JSON 转表格,粘贴数据 → 选分隔符与表头 → 导出 CSV → Excel 打开。适合几十行到几千行、结构规整的数据。
三个必须注意的点:
- 导出的是 CSV,不是 xlsx。Excel 打开 CSV 时默认按系统编码猜,中文可能乱码。用「数据 → 从文本/CSV」并显式选 UTF-8 更稳。
- 以
0开头的编号会掉零。"007"在 CSV 里是文本,Excel 会自动转成数字 7。导入时把该列设为文本,或者在 JSON 里给它加个前缀。 - 长数字会变科学计数法。身份证号、订单号超过 15 位就会精度丢失,这类字段在 JSON 里本来就该是字符串,导入后也要保持文本格式。
三、方法二:Excel 自带 Power Query(可复用)
数据每周都要更新时,用 Excel 内置的 Power Query,配置一次以后点「刷新」就行:
- 「数据」→「获取数据」→「自文件」→「自 JSON」;
- 选中文件后进入 Power Query 编辑器,看到的是
List/Record结构; - 点列标题右侧的展开图标,逐层展开嵌套字段;
- 确认列名与类型后,「关闭并上载」。
好处是嵌套能一层层展开成多列,而且类型可以手动指定;代价是第一次配置需要理解 List 和 Record 的区别——List 是数组,Record 是对象,展开方向不一样。
四、方法三:Python + pandas(字段多、要清洗时)
import pandas as pd
# 对象包数组:先取到列表那一层
rows = pd.read_json('data.json')['data']
# 嵌套字段展开成多列
frame = pd.json_normalize(rows, sep='_')
frame.to_excel('out.xlsx', index=False)
json_normalize 的关键参数是 sep,它决定嵌套字段展开后的列名风格,user_name 比 user.name 在 Excel 里更好用。数组套数组(比如 tags)需要额外一步 explode:
frame = frame.explode('tags')
这一步会把一行拆成多行,是唯一能保留「一对多」关系的做法,代价是其余字段重复。
五、方法四:Node 脚本(要接进流水线时)
import { readFileSync, writeFileSync } from 'node:fs';
const rows = JSON.parse(readFileSync('data.json', 'utf8'));
const headers = [...new Set(rows.flatMap((row) => Object.keys(row)))];
const escapeCell = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
const lines = [
headers.join(','),
...rows.map((row) => headers.map((key) => escapeCell(row[key])).join(',')),
];
writeFileSync('out.csv', '\uFEFF' + lines.join('\n'), 'utf8');
两个细节别省:开头写 \uFEFF(BOM)让 Excel 认 UTF-8;单元格里的双引号要成对转义成 "",否则列会错位。
六、转换一定会丢的三样东西
| 丢失项 | 表现 | 补救 |
|---|---|---|
| 类型信息 | 数字、布尔都变成文本或 TRUE/FALSE |
导入后手动设列类型,或用 Power Query 指定 |
| 嵌套层级 | 深层字段被压成 [object Object] |
用 json_normalize 或逐层展开,别直接 String(obj) |
| 一对多关系 | 数组被塞进一个单元格 | explode 拆行,或单独建一张关联表 |
另外,null 与「字段不存在」在表里看起来一样(都是空单元格),但业务含义不同。需要区分时,在 JSON 里把 null 显式转成字符串 "null",或者加一列 _has_field 标记。
七、回头验证:别只看第一行
转完至少抽查三处:
- 记录条数:CSV 行数应等于数组长度 + 1(表头),少一条通常是末尾换行被吞;
- 空值率最高的列:空得多说明键名不一致,回去看原始 JSON 是不是有两种写法(
userId与user_id); - 最长的那一行:嵌套数组通常在这里,确认没有被截断。
需要反向操作(Excel/CSV 转回 JSON)时,用 CSV 转 JSON,注意表头会被当作键名,改表头等于改字段名。
常见问题
在线工具、Power Query 和 pandas 该如何取舍?
在线工具适合几十行到几千行、结构规整、只转一次的数据,粘贴后选分隔符与表头即可导出 CSV。Power Query 配置一次后点刷新就行,适合每周都要更新的数据。字段多、需要清洗时用 Python + pandas 的 json_normalize,要接进流水线再写 Node 脚本。
为什么转成 CSV 后中文会乱码?
在线工具导出的是 CSV 而不是 xlsx,Excel 打开 CSV 时会按系统编码猜,UTF-8 无 BOM 的中文就会乱码。导出时在开头写 \uFEFF(BOM),或在 Excel 里用「数据 → 从文本/CSV」并显式选择 UTF-8。
能否保留原始 JSON 的嵌套层级?
可以,但要逐层展开而不是转成字符串:Power Query 能点列标题的展开图标一层层展开成多列,pandas 用 json_normalize 配合 sep 把嵌套字段拆成列。深层字段直接 String(obj) 只会得到 [object Object],数组套数组还要额外做一步 explode。