JSON转CSV转换器

把 JSON 记录数组摊平成表格:嵌套对象与数组按策略展开,字段取全部记录的并集,输出严格按 RFC 4180 转义,记录用 CRLF 分隔。

字段数10
数据行15
输出行数16
输出字节891
加 BOM 字节894
加引号单元格3

字段并集:id | name | tags.0 | contact.email | contact.city | note | tags.1 | contact.zip | level | tags.2

提示:源码框里按 Ctrl + Enter 转换(单独按 Enter 只是换行);「预览行数」输入框里按 Enter 会直接重算。结果区里第 3 条记录的 note 跨了物理上的两行——那是 RFC 4180 允许的「字段内换行」,整格被引号包住,Excel 与 pandas 都能正确读回来。

预览表格(前 12 行,共 15 条记录)

#idnametags.0contact.emailcontact.citynotetags.1contact.zipleveltags.2
11用户1vipu1@example.com北京含,逗号
22用户2vipu2@example.com上海He said "hi"new
33用户3u3@example.com广州第一行 第二行
44用户4vip深圳第 4 条new
55用户5vipu5@example.com杭州第 5 条
66用户6u6@example.com成都第 6 条100000
77用户7vipu7@example.com武汉第 7 条
88用户8vipu8@example.com西安第 8 条new
99用户9u9@example.com南京第 9 条
1010用户10vipu10@example.com重庆第 10 条new
1111用户11vipu11@example.com长沙第 11 条3
1212用户12vipu12@example.com苏州第 12 条oldtop
1313用户13vipu13@example.com青岛第 13 条
1414用户14vipu14@example.com厦门第 14 条new
1515用户15u15@example.com天津第 15 条

使用方法

  1. 把 JSON 粘进上面的输入框。顶层应当是一个对象数组 [{...}, {...}];顶层是单个对象时会被当成只有一条记录处理。页面打开时输入框里已经放了 15 条记录,结果区同时给出了它们的 CSV。
  2. 选「嵌套值的扁平化策略」。默认点号路径:contact.city 变成一列 contact.city,数组按下标拆成 tags.0、tags.1。改成「整体序列化」则嵌套值整块变成一个 JSON 字符串塞在一格里;改成「只保留标量」则嵌套的列直接不要。
  3. 看统计条:示例的六个数字是字段数 10、数据行 15、输出行数 16、输出字节 891、加 BOM 894、加引号单元格 3。这六个数字随选项实时变化。
  4. 在源码框里按 Ctrl + Enter(macOS 用 Cmd + Enter)重新转换;单独按 Enter 只换行。在「预览表格显示前几行」输入框里按 Enter 会直接重算。
  5. 拿走结果:「复制 CSV」把结果区文本送进剪贴板;「下载 CSV」导出带 BOM 的 UTF-8 文件,Excel 双击打开不乱码;「下载字段清单 JSON」导出不带 BOM 的字段定义,供程序二次读取。

这个 JSON转CSV转换器 能解决什么问题

一是把接口返回的 JSON 倒进表格软件。调接口拿到的是一段 JSON 数组,想丢进 Excel 做透视、排序、筛选,手工复制粘贴会把字段对错位。本转换器先求出所有记录的字段并集再逐格填值,所以哪怕第 6 条记录多了一个 zip、第 11 条多了一个 level,列也不会错位。

二是处理字段不齐的脏数据。真实导出里「有的记录有这个字段、有的没有」是常态。本页的做法是取并集:字段顺序按首次出现的先后排定,缺这个字段的记录在该列留空。示例里 tags.0 来自第 1 条、contact.zip 来自第 6 条、level 来自第 11 条、tags.2 来自第 12 条,最后排成 10 列。

三是不再被逗号和引号带偏。手工拼 CSV 最常见的错误是字段里有一个逗号,整行就多出一列。这个 JSON转CSV转换器对每个单元格单独判断:含逗号、含双引号、含换行的值才会被双引号包起来,值里的双引号写成两个。示例里 "含,逗号"、"He said ""hi"""、"第一行⏎第二行" 三格按这条规则处理,其余 147 格保持裸值。

四是还原成真正的二维表。CSV 没有嵌套概念,tags: ["vip","new"] 这种结构必须先摊平。点号路径策略会把它变成两列 tags.0 与 tags.1,做列筛选和透视时比一整串 JSON 好用得多。

本页不做这些事:不合并单元格、不做多行表头、不做类型推断(不会把 007 当数字、也不会把 true 转成布尔)、不把 CSV 转回 JSON(反方向请用页面底部的工具)、不校验字段的业务含义。它只负责把 JSON 忠实、可逆地摊成一张符合 RFC 4180 的表。以上四件事合起来,就是 JSON转CSV转换器 的全部职责。

转换原理:递归扁平化、字段并集与 RFC 4180 转义

① 调用的函数与算法。三步,每步都是明确的名字:解析用 JavaScript 内置的 JSON.parse(实现 ECMA-404 / RFC 8259);扁平化用自写的递归函数 flatten,深度优先遍历对象与数组,把访问路径拼成字段名;序列化用自写的 esc 逐格判断是否需要加引号。没有任何第三方 CSV 库参与。

② 点号路径是怎么拼出来的。递归时带一个 path 参数:进入对象的某个键,就拼成 父.键;进入数组的第 i 项,就拼成 父.i;到了标量才把 [path, 值] 记下来。所以 {"contact":{"city":"北京"}} 产出字段 contact.city,{"tags":["vip","new"]} 产出 tags.0 与 tags.1。空对象和空数组不产出任何字段——它们没有可以落脚的标量,所以第 2 条记录的 tags: [] 在 tags.0 这一列留空。

③ 字段并集的顺序规则。把所有记录按顺序各跑一遍扁平化,每得到一个字段名就检查它是否已经出现过,没出现过就追加到数组末尾。于是字段顺序 = 首次出现的先后,而不是字母序,也不是最长记录优先。示例的 10 个字段就是这么来的:第 1 条贡献 6 个,第 6 条贡献 contact.zip,第 11 条贡献 level,第 12 条贡献 tags.1 和 tags.2。想改成字母序,先转换再用「JSON按键排序工具」处理源数据即可。

④ RFC 4180 的转义规则。这份 RFC 把 CSV 定死为:字段之间用逗号分隔,记录之间用 CRLF(\r\n,即 U+000D U+000A 两个字节)分隔,最后一条记录后的 CRLF 可选;字段可以不加引号,但如果值里含逗号、双引号或换行,就必须整个用双引号包起来;引号里的双引号要写成两个双引号。本页严格照这套做,所以 He said "hi" 输出成 "He said ""hi""",第一行的引号、第二行的双写、最后一行末尾的引号一个都不少。

⑤ 输出与输入之间少了什么。JSON 的类型信息会被抹掉——CSV 只有文本。数字 1 和字符串 "1" 输出后长得一模一样;true 变成 true 四个字母;null 变成空单元格,跟「字段缺失」和「空字符串」在 CSV 里无法区分。如果下游要区分这三者,别用 CSV,改用 JSON 或 TSV 并额外带一个类型列。

⑥ 为什么默认开表头、默认开 CRLF。RFC 4180 允许表头可选,但 Excel、Numbers、pandas(read_csv 默认 header=0)都默认把第一行当列名,不开表头反而要手工补参数。CRLF 同理:这是 RFC 规定的记录分隔符,Windows 系工具和 Excel 的原生写法,只多占 15 个字节(16 行 → 15 个换行),换来的兼容性远大于这点体积。

⑦ 编码与 BOM 分岔。Excel 在 Windows 上读 UTF-8 的 CSV 时,如果没有字节顺序标记(BOM,UTF-8 下是 EF BB BF 三个字节),会按系统本地代码页解码,中文直接变乱码。所以导出的 .csv 前面加上 BOM:示例从 891 字节变成 894 字节。但 JSON 绝不能带 BOM——按 RFC 8259,JSON 文本的第一个字符必须是值的一部分,BOM 会让 JSON.parse 直接抛 Unexpected token。所以「字段清单 JSON」这个按钮导出的文件刻意不带 BOM。

完整示例(数值仅作演示)

示例条件与页面打开时完全一致:15 条记录、点号路径、带表头、CRLF。实测结果:

同一份输入换扁平化策略,字段数与体积的差别很大,这就是这个选项唯一的影响面:

策略字段数字段清单输出字节
点号路径(默认)10id · name · tags.0 · contact.email · contact.city · note · tags.1 · contact.zip · level · tags.2891
整体序列化6id · name · tags · contact · note · level1408
只保留标量4id · name · note · level389

三种策略的体积顺序值得记一下:整体序列化最大(1408 字节,比点号路径多 58%),因为它把 tags、contact 两列的键名逐条重复写了 15 遍;只保留标量最小(389 字节),代价是丢掉了 contact.email 这类信息。要拿去做透视表就选点号路径,要原样搬走数据再解析就选整体序列化。

单格转义的实际效果,逐个数一遍:

原始值输出单元格为什么要这样
用户1用户1不含特殊字符,不加引号
含,逗号"含,逗号"含逗号,不加引号会被当成分隔符,整行多一列
He said "hi""He said ""hi"""含双引号,加引号且把内部引号双写
第一行⏎第二行"第一行⏎第二行"含换行,加引号后换行留在同一格内,不新起一条记录
null(空)null 输出为空单元格,与「缺字段」「空串」在 CSV 里不可区分
=1+1=1+1(勾选防护后为 "'=1+1")等号开头会被 Excel 当公式,防护开启时前面加一个单引号

嵌套扁平化策略与输入范围对照表

下面把输入条件、选项和结果放在一起,方便你预判输出。表里的数字都来自上面的 15 条示例。

输入 / 选项能否处理结果
空输入或只有空白拒绝报「输入为空」,结果区与预览表一起清空
超过 20 万字符拒绝报出实际字符数并说明上限,避免超大 JSON 把页面卡住
JSON 语法错误(如多余的逗号)拒绝报出出错的行:列,例如 第 3 行第 26 列,并复述引擎的原始提示
值没加引号({"name": 张三})拒绝定位到那个非法字符的行:列,提示 JSON 的字符串必须用双引号
JSON 被截断(括号没闭合)拒绝报「输入在第 X 行第 Y 列结束」,这是复制粘贴截断最常见的形态
顶层是数组处理每个元素按一条记录处理
顶层是单个对象处理当成只有一条记录,输出 1 行数据
顶层是字符串 / 数字 / true / null拒绝报出实际的顶层类型,说明需要对象或对象数组
空数组 []拒绝报「里面没有任何记录」
[{},{}] 全是空对象拒绝报「推不出字段」,而不是给一个 0 列的空 CSV
标量数组 [1,2,3]处理元素归到名叫 value 的单列,输出 3 行
嵌套深度任意处理点号路径按层级拼名;深度只受 JavaScript 调用栈限制,1 万层以内没问题
预览行数填 0 / 501 / 小数拒绝报「只能填 1~500 的整数」,不四舍五入

结果边界、精度与失败路径

常见问题

为什么导出 CSV 要加 BOM,字段清单 JSON 却坚决不加?

Excel 在 Windows 上读 .csv 时,如果文件没有字节顺序标记,会按系统本地代码页而不是 UTF-8 解码,中文就变乱码;加上 EF BB BF 三个字节后 Excel 才会按 UTF-8 读。JSON 正好相反,RFC 8259 规定 JSON 文本第一个字符就必须属于那个值,BOM 会让 JSON.parse 抛出 Unexpected token。所以本页两种导出走两条路:CSV 带 BOM,JSON 不带。

嵌套对象和数组,到底该选哪种扁平化策略?

看下游怎么用。要丢进 Excel 做透视、排序、按城市或邮箱筛选,选点号路径,字段变成 contact.city 这种独立列最好用。要原样把数据搬到另一个系统再解析,选整体序列化,嵌套部分保持 JSON 结构不丢,代价是体积从 891 涨到 1408 字节。只想看几个标量字段的清单,选只保留标量,输出最干净(4 列、389 字节)。

我的长订单号变成别的数字了,是工具出 bug 吗?

不是,是 JSON 数字本身的精度上限。JSON 的数字按 IEEE 754 双精度读取,能精确表示的最大整数是 253−1 = 9007199254740991。9007199254740993 会被读成 9007199254740992,最后一位变了。唯一的解法是让源 JSON 把这类字段写成字符串:"orderId": "9007199254740993",这样它走文本路径,一个字符都不会丢。

字段顺序能不能按字母排?

本页按首次出现的先后排,因为这种顺序保留了源数据里字段的自然排布,通常比字母序更贴近业务含义。想按字母排,先把源 JSON 用「JSON按键排序工具」处理一遍再转,或者在表格软件里导入后自行排序。工具不会替你重排字段名,因为那会改变输出对源数据的可追溯性。

空数组和 null 为什么都变成空白单元格?

因为 CSV 里这三件事长得完全一样:字段缺失(记录里根本没这个键)、值为 null、值为空字符串 ""。示例里第 2 条的 tags: [] 在 tags.0 列留空,第 4 条的 email: null 在 contact.email 列留空,看起来没区别。如果下游必须区分它们,就不要用 CSV,改用保留类型的格式,或者在转换前给源数据补一个标记字段。

Excel 打开导出的 CSV,中文还是乱码怎么办?

先确认用的是「下载 CSV」而不是「复制 CSV」再手动保存——只有前者会写 BOM。如果已经带 BOM 还是乱码,多半是 Excel 之外的工具重新保存过文件、把 BOM 丢了。可以改用「数据 → 从文本/CSV」导入并手动指定 UTF-8 编码,或者直接用记事本(Windows 11 的记事本默认 UTF-8)打开确认文件本身是否正确。

CSV 公式注入是什么?要不要打开防护?

如果某个单元格的值以 =、+、-、@ 开头,Excel 会把它当公式执行,恶意数据可以借机制造外部请求或篡改显示内容。防护的做法是在值前面加一个单引号并强制加引号包住,让 Excel 把它当普通文本。代价是数据被改写了,所以默认关闭——只有当这份 CSV 会被别人用 Excel 直接双击打开时才建议勾上。

结果区里为什么有一行看起来断成了两行?

那是第 3 条记录的 note,源数据里本来就含一个换行符。按 RFC 4180,字段内换行是合法的,只要整格用双引号包起来,解析器就知道这两行属于同一条记录。Excel、Numbers、pandas 都能正确读回成一条记录。如果你看到的是断成两条记录,说明用的解析器不支持带引号的字段内换行,这种实现不完整。

相关工具