先分清:JS 对象字面量和 JSON
很多人从代码里复制一段对象,期望它「差不多就是 JSON」。差得还挺多。JavaScript 允许尾逗号、单引号、未加引号的键、注释、undefined。标准 JSON 这些都不认。编辑器里能跑的对象,粘到接口文档或配置文件里就会炸。
JSON 只承认六种值:对象、数组、字符串、数字、true/false、null。字符串必须双引号。键必须是字符串。
1. 最后一个元素后面多了逗号
从 TypeScript 或 ESLint 配过 trailingComma 的项目拷出来,最容易带上这个。
{
"id": 12,
"name": "order",
}
改成:
{
"id": 12,
"name": "order"
}
数组同样不行:[1, 2, 3,]。有些宽松解析器(JSON5、部分 YAML 转 JSON 工具)会吞掉尾逗号,你这边过了,同事用标准库一解析又挂。联调时以 RFC 8259 为准。
2. 单引号、未加引号的键
{'name': 'test'}
{name: "test"}
两行都非法。正确写法是 {"name": "test"}。Python 的 dict 打印、Mongo shell、部分日志框架会吐单引号,需要先替换再解析,不要手改几百行,容易漏。
3. 注释
VS Code 的 settings.json 实际是 JSONC,允许 // 和 /* */。标准 JSON 没有注释。从配置文件抠一段去当 API body,经常卡在注释上。
真要给人看结构,把说明写在旁边的文档里,或者用 JSON Schema 的 description 字段。不要在 payload 里夹注释碰运气。
4. NaN、Infinity、undefined
JSON.stringify({ a: NaN, b: Infinity, c: undefined }) 在浏览器里会变成 {"a":null,"b":null},c 直接丢掉。你以为发出去了,对端收到的是 null 或字段消失。
反过来,有的服务端(早期 PHP、某些日志)会写出 {"score": NaN}。这不是合法 JSON。约定用 null,或者改成字符串 "NaN" 并在文档里写清楚。
5. 字符串里的换行和引号没转义
{
"msg": "第一行
第二行"
}
JSON 字符串不能直接折行,要写成 "第一行\\n第二行"。内部双引号写成 \\",反斜杠写成 \\\\。从 Word、聊天软件粘过来的文本,有时带着弯引号 “”,解析器只认 "。
6. 重复键
{
"status": "ok",
"status": "fail"
}
规范不鼓励重复键,多数解析器静默留最后一个。表面上「能 parse」,两边读到的值可能不一样。合并配置、手写 mock 时特别容易发生。树视图里如果同一层出现两个同名键,先当事故查,不要当特性用。
7. 文件开头的 BOM
Windows 记事本另存为 UTF-8 时可能带 BOM。第一个字符是不可见的 U+FEFF,报错常写 Unexpected token 在 position 0。用十六进制看文件头,或在编辑器里「以 UTF-8 无 BOM 保存」。
8. 把好几个对象糊在一起
日志里常见一次贴三行对象,中间没有包成数组:
{"id":1}
{"id":2}
这叫 JSON Lines,不是一个 JSON 文档。要么改成 [{...},{...}],要么按行拆开。HiJSON 支持拖入 .jsonl,详见 JSON Lines 与日志分析。
建议的排查顺序
- 看报错列号。多数实现给的是「解析器放弃的位置」,真正语法错误常常在它前面几个字符。
- 先查尾逗号和单引号,这两项占日常失败的一大半。
- 还有问题就搜
//、NaN、undefined、中文弯引号。 - 仍然过不了,把原文存成文件,看编码和 BOM。
- 确认它是不是 JSONL、JSONP(
callback({...}))或 YAML 误贴。
HiJSON 解析失败会在输入框下方给出位置。修好再点解析,或 Ctrl+Enter。格式化按钮只对已经合法的文本有意义,非法文本先过语法再谈缩进,见 格式化指南。
常见问题
- Postman 里能看,粘到这里报错?
- 有的客户端展示层会「美化」或容忍尾逗号。复制时选 raw body,不要从预览面板抄。
- 数字特别大,解析后变了?
- 这不一定是语法错误。JavaScript 安全整数到 2^53-1,再大的订单号建议当字符串传。语法过了但值漂了,属于语言限制,见 多语言解析。