DevFormatLab
← 返回博客列表

如何像专家一样验证与调试 JSON

作者 DevFormatLab Editorial·7 分钟阅读
JSON调试工作流教程

一份坏掉的 JSON 载荷,根因几乎总是确定的——输入里某一个字节错了。难点是把它定位在一个 200 KB 的 API 响应、4 MB 的配置文件,或者一段流式 NDJSON websocket 帧里。本文是我们内部用的工作流——也是客户拿着让他们的流水线崩掉的负载发给我们时,我们跑的同一套操作。

90 秒分诊

把出问题的文本粘到本站的 JSON 格式化工具里。页面底部会报行号与列号。先把这两个数字记住,再去看解析器的错误文本——因为解析器的位置常常差一,或者按码元而不是字符算,否则你会追着一个不存在的鬼魂查一下午。

一旦知道行号与列号,从那点倒推。真正出错的形式几乎只有这三种:

  • 未转义字符:字符串里冒出来的裸双引号、字面换行、裸反斜杠。
  • 结构错误:缺少闭合大括号、最后一个元素后多出来的逗号、两个元素之间 ,, 这样的空分隔。
  • 编码错误:UTF-8 BOM、被错认为 UTF-8 的 Latin-1 字节、被截断的代理对。

生产中八类错误

我们调查过的每一份「能解析但用不了」的报告都恰好属于下面八类之一,顺序也大致就是真实 bug 报告里出现的频率顺序。

  1. 尾逗号。{"a": 1, "b": 2,}——2 后的逗号非法。JSON 在数组和对象里都禁止尾逗号;JavaScript 在数组/对象字面量里允许;很多 YAML 导出器输出 JSON 时带尾逗号,因为 YAML 本身允许。修法是一行正则:s/,\s*([}\]])/$1/g

  2. 单引号字符串或未引号 key。{'a': 1}{a: 1} 都非法。JSON 在所有地方都要求双引号——key、字符串值,都一样。修法是统一用双引号;要写一个在字符串内能正确跳过撇号的正则有点烦,请直接用 JSON 格式化工具的树视图快速定位到错误点。

  3. 注释。JSON 不支持 ///* */ 注释。JSON5 支持;如果源文件带注释,要么接受 JSON5(牺牲对严格下游解析器的兼容性),要么在上游用正则剥掉注释。

  4. Unicode 转义。\x41\e、单独的 \ 都不合法。JSON 只接受九种转义:\"\\\/\b\f\n\r\t,以及 \uXXXX(恰好 4 个十六进制位,不少也不多)。其他一律拒绝。

  5. 带前导零的数字。0123 非法;0.123 合法;"0123" 合法(它是字符串)。JSON 禁止整数上的前导零,原因和 C/Java/Python 历史上一样:0123 看起来像八进制,而 JSON 没有八进制。

  6. NaN、Infinity、undefined。这些根本不属于 JSON。生产者写出裸的 NaN token 就是不符合规范。JSON.stringify 拒绝输出它们——它会替换为 null,这是文档化的逃生口。

  7. 编码错误。带 BOM 的 UTF-8 文件、被错标成 UTF-8 的 Latin-1 文件、SQL Server 导出的 Windows-1252 文件、日文财务系统的 Shift-JIS 文件——对严格的 UTF-8 解析器来说全都表现为「非法 JSON 字符」。第一步始终是在上游做编码检测并重新编码,工作流参考 CSV 编码指南

  8. 截断的输入。网络超时、部分文件写入、管道破裂,都会让你拿到一段看起来不错但中途突然结束的 JSON。错误报告会显示一个接近缓冲区末尾的位置。修生产者,不要修解析器。

JSON 能解析但程序仍然崩

这才是真实系统中最常见、也最难调试的情况——每个工具都会告诉你「JSON 合法」。问题在语义,不在语法。JSON 比对工具 在这里是合适的选择:把你的负载和已知正常的参考并排粘进去,结构化视图会列出所有不同的路径。

我们一次又一次看到的模式:

  • 字符串 vs 数字。API 期待 "42",收到 42,反之亦然。JSON 区分不了「用户年龄作字符串」还是「用户年龄作数字」——只有消费方能区分。金额、ID、任何必须精确往返的值编成字符串;计数、尺寸、参与算术的值编成数字。
  • null vs 缺失。{"name": null}{} 在几乎所有消费方里语义都不同。如果你的序列化器默认省略空字段,{"name": null} 就变成了 {},消费方那侧的 obj.name ?? defaultValue 就走 defaultValue 而不是 null。二选一、坚持到底;写到文档里;在对侧加测试。
  • 大小写敏感。"Username" vs "username" 差一个字符,JSON 没法解决。服务侧做大小写不敏感匹配会在一层隐藏 bug,下一层又冒出来。
  • 日期格式漂移。有产方输出 ISO 8601 字符串("2026-08-06T12:34:56Z"),有输出 epoch 秒(1754483696),有输出 epoch 毫秒(1754483696000),还有一两个写得很差的产方输出微软 JSON Date 格式("\\/Date(1754483696000)\\/")。两端都把格式写进文档,并在接收端验证。

把工作流建到工具里

只要你维护的系统还在接触 JSON,你就会每周在搜索框里粘贴同样字符两三次。把肌肉记忆建起来:

  1. 第一站:粘到 JSON 格式化工具。看行号与列号。
  2. 第二站:解析器接受了但程序崩,把你的负载和已知正常的参考都粘进 JSON 比对工具,看结构化差异。
  3. 第三站:如果输入来自第三方 API,把原始字节(不是解析后的值)打进日志,下次 bug 再现时就有重放依据。

肌肉记忆一旦立起来,一份坏掉的 JSON 负载就变成 90 秒修复而不是一下午。工具:JSON 格式化工具JSON 比对工具,以及 JSON 参考指南 里的规范原文。

相关工具