JSON 解析报错的常见原因与修复方法
大多数 JSON 解析错误都来自几类常见失误:多余的逗号、单引号字符串、注释、未加引号的键、NaN 或 undefined 之类的值,或是从文档里复制来的弯引号。JSON 比它所模仿的 JavaScript 要严格得多,所以在人看来没问题的代码,解析器可能会拒绝。错误信息会指出行号和列号,修复点通常就在该位置或其前面一两个字符处。
JSON 格式化JSON 无法解析免费使用JSON 强制执行的规则
一个 JSON 文档只能是一个值:花括号包裹的对象、方括号包裹的数组、字符串、数字、true、false 或 null。在这些值的内部:
- 所有键和字符串都使用直双引号,例如 "name"。
- 逗号用于分隔各项,对象或数组的最后一项后面不能有逗号。
- 数字不能带正号,NaN、Infinity 和 undefined 既不是合法的数字,也不是合法的值。
- 完全不允许注释。
- 键必须是字符串,所以像 name: 这样未加引号的键是无效的。
有些解析器默认会接受其中一部分写法,有些工具也会为了方便而接受带注释的 JSON。这种宽松只会把问题藏起来,直到文件交给更严格的读取方才暴露,所以应当直接写成严格的格式。
读懂错误信息
解析器会报告它无法继续的第一个位置。错误信息会说明问题并给出位置,通常是行号和列号。下面是一个小文件,数组里有一个多余的逗号,最后一个属性后面也有一个:
{
"name": "Ada",
"tags": ["a", "b",],
}
Python 会报出这样的错误:"Illegal trailing comma before end of array: line 3 column 20"。不同工具的措辞各不相同,一些较旧的解析器只会说"Unexpected token"并给出字符偏移量。请跳到报告的位置,然后看它前面的那个字符。真正的错误往往是逗号、引号或花括号,位置比报告的地方早一两个字符。
Python 解析器还有几条常见报错,以及它们通常的含义:
- 对于 '{'a': 1}',报错"Expecting property name enclosed in double quotes",通常是单引号键或未加引号的键。
- 在你预期数字或字符串的位置报"Expecting value",往往是弯引号,因为解析器把它当成了未知字符。
- 报"Expecting ',' delimiter",通常是两项之间缺少逗号,或者数据中间夹着注释。
弯引号与复制来的文本
弯引号最容易让人困惑,因为它们看起来和直引号几乎一样。从文字处理软件、网页或聊天消息里复制的 JSON 文件,可能含有弯双引号。文件在你看来没问题,解析却失败了,因为解析器把“x”当成了未知字符,而不是字符串的定界符。
隐藏字符也会造成同样的失败。两个值之间的不间断空格,在解析器看来并不是空白。在手动修复结构之前,请先删除不可见字符,然后再修复引号。弯引号指南介绍了如何安全地把它们改回直引号。
单引号、注释与未加引号的键
许多开发者写的类 JSON 数据,是在一种允许更多写法的语言里完成的:
- 单引号在 JavaScript 和 Python 字面量中是合法的,但 JSON 要求双引号。把 {'a': 1} 改成 {"a": 1}。
- 诸如
//或/* */的注释必须删除。如果需要保留说明,可以放到单独的字段里,或者使用为配置文件设计的格式。 - 未加引号的键在 JavaScript 对象字面量中很常见。加上引号即可。
- NaN 和 undefined 不是 JSON。缺失的值用 null 表示;如果值是文本,就用字符串。
查找替换时要小心,不要一刀切。把每个单引号都换成双引号,会破坏任何包含撇号的字符串,例如 "Ada's notes"。请先在查找替换中预览每一处匹配,看清哪些引号会被改动。
一步步修复结构
- 把文件粘贴到 JSON 格式化工具中。格式化后结构会一目了然,错误也会显示行号和列号。然后点击修复,它会删除注释和多余的逗号。它不会改动单引号或弯引号,这些需要你自己修。
- 每次只修第一个错误,然后重新检查。一个错误可能会在后面引发好几个错误。
- 检查每个左花括号或左方括号是否都有对应的右括号,并确认嵌套层次是你想要的。
- 用你的应用所使用的解析器来验证最终文件,而不要只依赖网页工具。不同解析器之间会有细微差别。
能够解析的文件,不一定就是你想要的文件。请用 JSON Schema 校验来发现缺失的字段或类型错误的值,或者对比两个 JSON 文档,看看不同版本之间改动了什么。
特殊情况
- 生成文件中的多余逗号。 有些工具会写出这种逗号。如果你是手动拼接字符串来生成 JSON,请改用所用语言的序列化器,它输出的是合法格式。
- 重复的键。 JSON 允许重复的键,但大多数解析器只保留最后一个值。重复的键就是一个等着出事的隐患。
- 大数字。 非常大的整数在某些解析器里可能丢失精度。因此,如果标识符长到超出解析器能精确表示的范围,就把它存成字符串。CSV 转 JSON 指南在 ID 问题上也有同样的说明。
快速解答
为什么我的 JSON 看起来正确,却解析失败?
常见原因包括多余的逗号、单引号、注释,或者从文档里复制来的弯引号。请检查错误信息中的位置,以及该位置前面的那个字符。
JSON 可以有注释吗?
不可以。JSON 标准不允许注释。请删除它们,或者把说明移到单独的字段里。格式化工具的修复按钮会替你删除注释。
JSON 里应该用什么代替 undefined?
如果某个值是有意缺失的,就用 null;或者直接省略这个键。undefined 是 JavaScript 的值,在 JSON 中没有对应的表示方式。
由 AI 辅助翻译自英文原文。
评论
还没有评论。快来抢沙发。


