关于 JSON 转表格与 CSV
JSON 转表格工具接收一个 JSON 对象数组 —— 也接受单个对象,把它当作只有一行的数组 —— 从出现过的键推导出列集合,把记录渲染成可以横扫一眼的表格,并把同样这些行导出为 CSV。想回答「这批记录里哪一条少了字段」,它是最快的办法,而且不用写脚本。
JSON 和 CSV 对「形状」的理解并不一致。JSON 是一棵树:值可以是对象、数组或 null,同一个数组里的两条记录甚至不必带同样的键。CSV 是一个矩形:每行列数相同,每个单元格都是字符串,而且根本没有表示嵌套的办法。所以转换是在做决策 —— 哪个键变成列、键缺失时长什么样、本来就不扁平的值该如何落地。把这些决策弄清楚,才是「可信的表格」和「一张悄悄出错的电子表」之间的分界线。
如何使用这个开发者工具
- 把对象数组粘贴到 JSON 面板。单个对象同样可以,会生成一行;如果数组里装的是数字、字符串或嵌套数组,会被拒绝,因为它们没有可以成列的东西。
- 点击「生成表格」。列集合是所有行的键的并集,顺序按每个键第一次出现的先后排列,因此只在靠后记录里才出现的字段会被排到最后一列。
- 先看形状再看内容:空单元格标记的是「该记录没有这个键」,嵌套值则以内联 JSON 的形式显示。
- 需要电子表格副本时点「下载 CSV」。文件名为 table.csv,开头带 UTF-8 字节序标记,Excel 能用正确的编码打开。
- 在依赖导出结果之前,请把表格里显示为嵌套 JSON 的那些列和导出文件对照一遍 —— 两种渲染并不一致,下面的对照表说明了原因。
实例:表格和 CSV 不一致的地方
两条键集合参差不齐的记录,包含带引号的字符串、一个嵌套对象和一个数组。这里把表格和导出文件放在一起,因为它们说的并不是同一件事。
[
{ "id": 1, "name": "Ada, \"the Countess\"", "tags": ["admin", "beta"], "profile": { "region": "eu" } },
{ "id": 2, "name": "Grace", "tags": [], "active": false }
]id | name | tags | profile | active
1 | Ada, "the Countess" | ["admin","beta"] | {"region":"eu"} |
2 | Grace | [] | | false
"id","name","tags","profile","active"
"1","Ada, ""the Countess""","admin,beta","[object Object]",""
"2","Grace","","","false"有三处差异值得记住。表格把嵌套值渲染成 JSON,CSV 却是直接做字符串转换,于是对象变成了字面文本 [object Object],数组丢掉了方括号。空数组在屏幕上显示为 [],在文件里什么都不剩。而那个带引号的字符串在 CSV 里被正确处理了 —— 靠的是把内部引号写两遍,这是 RFC 4180 的规则,而不是反斜杠转义。
每种 JSON 值分别如何落到表格和文件里
CSV 的每一个字段(包括表头行)都用双引号包裹,值内部的双引号会被写成两个。这是 RFC 4180 的做法,也正因如此,值里的逗号和换行是安全的。不安全的是嵌套。
| JSON 值 | 表格单元格 | CSV 字段 |
|---|---|---|
| "Grace" | Grace | "Grace" |
| 5432 | 5432 | "5432" |
| false | false | "false" |
| null | null | ""(空) |
| 该行没有这个键 | (空) | ""(空) |
| {"region":"eu"} | {"region":"eu"} | "[object Object]" |
| ["admin","beta"] | ["admin","beta"] | "admin,beta" |
| [] | [] | ""(空) |
| "a, b" | a, b | "a, b" —— 引号把逗号留在了同一个字段里 |
| "say \"hi\"" | say "hi" | "say ""hi""" |
| "line1\nline2" | 单元格里显示为两行 | 引号内是一个真正的换行符,因此一条记录横跨两行 |
常见问题排查
明明是合法 JSON,却报解析错误。
成因 工具需要的是「记录」。顶层是对象可以,是对象数组也可以;但数组里装的是数字、字符串、另一个数组或 null 时,就没有任何东西能变成列。
解决办法 先把文档改形。如果记录被包在 {"data":{"items":[...]}} 这样的外壳里,请先用 JSONPath 测试器把数组取出来,再只粘贴那一段。
导出文件里某一列显示成 [object Object]。
成因 CSV 写出时对每个值做的是普通字符串转换,对象因此变成 [object Object],数组变成用逗号连接的列表。只有屏幕上的表格才会把嵌套值序列化成 JSON。
解决办法 粘贴之前先扁平化。把 profile.region 提升为顶层键 profile_region,数组也请自己拼成一个带分隔符的字符串,这样分隔符由你决定。
在电子表格里打开 CSV,结果执行了什么东西。
成因 以 =、+、- 或 @ 开头的单元格文本,会被 Excel 和 LibreOffice 当作公式。用引号包裹不是可靠的防御,因此一旦 =cmd|'/c calc'!A1 这种来自用户输入的值进了文件,有人双击打开的瞬间它就成了一次攻击。
解决办法 永远不要靠双击打开来自不可信数据的导出文件。请走电子表格的文本导入向导,把相关列显式指定为「文本」;或者在导出前给可疑值加上一个单引号前缀。
少了一列,或者空单元格含义不明。
成因 列来自「实际出现过的键」的并集,没有任何记录带的键根本不会出现。而一个空单元格可能意味着键缺失、值为 null、值是空字符串,或者值是空数组 —— 导出时这四种被压成了同一个空字段。
解决办法 导出前把记录规范化,让每个对象都带上全部键;对必须保持可区分的值,用一个哨兵值代替 null。
适合用这个工具的场景
- 把 API 响应当作记录横扫一遍,看看哪些对象缺字段、哪些字段类型不对。
- 不用写脚本,就把 JSON 夹具的内容交给习惯用电子表格的同事。
- 把同一个接口的两次调用各导出一份 CSV,然后做差异对比。
- 把一小段 JSON 日志变成可以排序、可以筛选的东西,用于排查问题。
应该换用别的工具的场景
- 判断文档是否合法、定位语法错误。JSON 格式化与校验工具会报出精确偏移量。
- 从层层嵌套的响应里取出记录数组。请先用 JSONPath 测试器选出来,再把结果粘到这里。
- 原样导出嵌套数据。CSV 没有表示树的办法;要么有意识地做扁平化,要么保持 JSON 或 NDJSON。
隐私与数据处理
文档的解析、表格的构建和 CSV 的生成全部在当前浏览器标签页内完成,下载文件由内存中的 Blob 直接产生,不经过任何服务器。记录型导出恰恰最容易夹带姓名、邮箱和账号 ID,因此粘贴前请把数组裁剪到几条有代表性的记录,用完后把下载的文件删掉。
相关开发者工具
常见问题
列的顺序是怎么定的?
按首次出现的先后。工具按顺序遍历记录并收集键,第一条记录的键排在最前,之后才出现的键依次追加。调整输入顺序就会调整列顺序 —— 如果下游导入是按位置取值的,这一点很关键。
为什么 Excel 打开我的 CSV 是乱码?
正常情况下不该乱:下载的文件开头就带 UTF-8 字节序标记,正是为了让 Excel 认出编码。如果仍然乱码,多半是文件被别的程序另存过、标记被抹掉了,或者导入时手动指定了别的编码。
能把嵌套对象正确导出吗?
按原样不行。请先扁平化 —— 要么把嵌套字段提升为带前缀的顶层键(比如 profile_region),要么把整棵子树序列化成一列 JSON 字符串、由消费方再解析回来。这两种都是明确的选择;默认的字符串转换不是。
工具会改动我的值吗?
它不会编辑 JSON,但表格和 CSV 都是「渲染」,而渲染是有损的。大整数在文档被解析的那一刻就已经丢了精度,嵌套值在导出时被转成了文本。请始终把 JSON 当作事实来源。
能粘贴多大的文档?
整个结构和渲染出来的表格会同时驻留在浏览器内存里,因此几千条记录很轻松,几万条就会让页面变卡。再大的量请改用命令行上的流式转换工具。
带引号的 CSV 字段能安全承载任意文本吗?
对逗号、引号和换行来说可以 —— RFC 4180 的引号规则覆盖这三种,而且导出时每个字段都加了引号。对公式注入则不行。引号并不能阻止电子表格去求值一个以 = 开头的单元格,这是电子表格的特性,不是文件格式的问题。