问题出在哪

CSV 是平面表格:固定列、每行一条记录。

JSON 是树形结构:对象里可以嵌对象,数组里可以套数组。

这两个形状对不上。所以「JSON 转 CSV」本质上不是格式转换,而是一次结构映射的决策——你得先决定那棵树怎么压平。

下面按嵌套程度分三种情况。

一、最简单:数组套对象

json[
  { "id": 1, "name": "张三", "age": 28 },
  { "id": 2, "name": "李四", "age": 32 }
]

这种直接转,没有歧义:

id,name,age
1,张三,28
2,李四,32

JSON 转 CSV 粘进去就出结果。

二、对象里嵌对象:扁平化成 a.b 列名

json[
  { "id": 1, "user": { "name": "张三", "city": "杭州" } }
]

嵌套对象本身是「一对一的属性」,压平就行,列名用点号连起来:

id,user.name,user.city
1,张三,杭州

注意:层级别太深。三层以上列名会长到没法看,而且下游用起来也痛苦。真遇到这种结构,多半说明数据模型该调整了。

三、数组里嵌数组:这里必须做选择

json[
  { "id": 1, "tags": ["前端", "React"] }
]

tags 有多个值,但一行只有一格。三种处理方式:

① 序列化成字符串 —— 最简单,但下游要再拆一次

id,tags
1,"[""前端"",""React""]"

② 用分隔符连起来 —— 可读性好,但值里本身有分隔符就废了

id,tags
1,前端|React

③ 展开成多行 —— 一行变两行

id,tags
1,前端
1,React

这种方式没有信息损失,但行数变了,下游做统计时要注意去重。

三种策略怎么选

策略 优点 代价
扁平化(a.b) 无信息损失,一列一个值 列名变长,层级别太深
序列化(JSON 字符串) 简单、无损 下游要再解析一次
拆多行 便于分组统计 行数膨胀,主键重复
拆多张表 最规范 CSV 装不下关系,得改交付格式

判断依据:目标读者是人还是程序。给人看的报表用扁平化;给程序批处理用序列化或拆多行。

中文乱码:Excel 打开 CSV 的正确姿势

这是转完 CSV 之后最常踩的坑:用 Excel 打开,中文全是乱码。

原因:CSV 文件默认存成 UTF-8,而中文版 Excel 默认按 GBK 解读,两边对不上。

两个解法

① 存成「UTF-8 with BOM」 —— 在文件开头写一个 BOM 标记,Excel 看到就知道这是 UTF-8。这是最省事的办法,Windows 用户拿到就能直接双击打开。

② 用 Excel 的「数据 → 从文本/CSV」导入 —— 手动指定编码为 UTF-8。不改变文件,但每次都要操作一遍。

如果 CSV 是要发给别人的,建议直接选带 BOM 的;如果是喂给程序读的,不要 BOM(很多解析库会把 BOM 当成内容的一部分,反而出错)。

字段不一致怎么办

json[
  { "id": 1, "name": "张三" },
  { "id": 2, "name": "李四", "vip": true }
]

第二条多了个 vip 字段。标准做法是取所有对象的字段并集作为表头,缺失的位置留空:

id,name,vip
1,张三,
2,李四,true

不要因为「第一条没有 vip」就把这列丢掉——那会静默丢数据。

一个检查清单

转完 CSV 之后对着过一遍:

  • 行数对不对(数组里几个对象就该几行,拆多行策略除外)
  • 列名有没有重复(嵌套路径拼出来的列名偶尔会撞)
  • 值里含逗号、引号、换行的字段有没有被正确加引号转义
  • 中文在目标软件里打开正常吗
  • 大整数字段有没有被 Excel 自动转成科学计数法

最后一条特别容易中招:Excel 会把超过 11 位的数字显示成 1.23E+15,而且不可逆。订单号、身份证号这类字段,转 CSV 前最好先转成字符串。

动手试

把 JSON 粘到 JSON 转 CSV 就能转。结构不合法的话,先用 JSON 格式化 校验一遍再转,能少走弯路。