JSON 入门:格式、语法与常见错误
JSON 是今天 Web 世界交换数据的事实标准。接口返回它,配置文件用它,日志里也全是它。它的规则极少,但每条规则被违反时,报错信息都相当隐晦。这篇入门讲清楚 JSON 的语法骨架,并整理一份常见解析错误对照表。
JSON 是什么,为什么流行
JSON(JavaScript Object Notation)诞生于 2000 年代初。它如今由 RFC 8259 与 ECMA-404 标准化。它取了 JavaScript 对象字面量里最通用的子集,却刻意做到与语言无关。Python、Java、Go 等几乎所有语言都有解析器。相比 XML,它去掉了冗长的标签闭合,体积更小。浏览器里一行 JSON.parse 就能变成对象。这是它取代 XML、成为 Web API 默认格式的直接原因。
六种数据类型与语法规则
一个合法的 JSON 值只能是六种类型之一。字符串用双引号包裹。数字不支持八进制、十六进制写法。布尔值是小写的 true / false,null 也是小写。对象是大括号里的键值对,数组是方括号里的有序值。围绕它们有四条最容易踩的硬规则:
- 键必须是双引号字符串,单引号或不加引号都非法。
- 没有注释,// 与 /* */ 都会导致解析失败。
- 最后一个成员后面不能有逗号,尾逗号非法。
- 字符串内部不能直接换行,要写成 \n;反斜杠要写成 \\。
还有一个隐蔽陷阱。JavaScript 按 64 位浮点数处理数字,超过 2^53 的整数会悄悄丢失精度。订单号、雪花算法 ID 常见这种整数。接口设计时应把这类 ID 以字符串传输。
嵌套结构怎么读
真实数据几乎都是嵌套的:对象里套数组,数组里再套对象。比如接口返回的用户列表,要按 data.items[0].name 这样的路径去读。先取 data 对象的 items 数组,再取第 0 个元素的 name 字段。判断结构最快的办法,是用本站的 JSON 格式化工具把压缩成一行的响应展开,缩进层级一眼可见。容器类型看括号形状:方括号是数组,按序号访问;花括号是对象,按键名访问。
十大常见解析错误对照表
不同解析器的报错文案略有差异。下面以 Chrome / Node.js 的措辞为例,原因与修法是通用的。
| 报错信息(示例) | 常见原因 | 修复方法 |
|---|---|---|
| Unexpected end of JSON input | JSON 被截断,缺少右括号或引号。 | 格式化后检查括号配对,确认响应完整。 |
| Unexpected token } | 尾逗号 | 删除最后一个成员后的逗号。 |
| Unexpected token ' | 用了单引号 | 键与字符串全部改双引号。 |
| Expected property name or '}' | 键没有加双引号 | 所有键都加双引号。 |
| Unexpected token / | 写了 // 或 /* */ 注释 | 删除注释,说明移到外部文档。 |
| Bad escaped character | Windows 路径 C:\Users 只写了一个反斜杠。 | 写成 C:\\Users,或改用正斜杠。 |
| Unexpected token < in JSON | 拿到的是 HTML 而非 JSON,来自 404 或错误页。 | 检查接口地址与 HTTP 状态码。 |
| Unexpected token u in JSON at position 0 | JSON.parse(undefined)。变量未赋值。 | 解析前先判空。 |
| Unexpected number | 数字写了前导零,如 012 | 去掉前导零。 |
| Unexpected token N | NaN、Infinity 直接写进了 JSON | 改用 null 或字符串表示。 |
JSON、XML、CSV 怎么选
- Web API 与配置文件:首选 JSON。体积小、层级表达自然、生态默认支持。
- 需要命名空间、混合内容,或与老系统(SOAP、Office 文档)交互:XML 仍不可替代。本站的 XML 格式化工具可以帮你理清层级。
- 纯表格数据、要进 Excel:CSV 最省事,但它没有嵌套、没有类型,逗号引号转义是重灾区。需要转换时可用本站的 CSV 转 JSON 工具。
格式化、压缩与 Schema 校验
格式化和压缩是同一份数据的两种形态。调试、评审、写文档时用格式化,带缩进与换行,人读得快。接口传输、落盘存储用压缩,只留一行,体积更小,解析也略快。一个实用习惯:线上排查“字段取不到”的问题时,先把原始响应丢进格式化工具。多数 bug 三十秒内现形。
当团队对“这个字段必须有、那个字段只能是数字”有了共识,就该上 JSON Schema 了。它用 JSON 本身描述数据的结构与约束,包括类型、必填、枚举、取值范围。配合校验库,它能在数据进入业务代码之前把不合规数据挡在门外,是接口联调和配置校验的常用手段。
常见错误与排查
除了对照表里那些当场报错的语法问题,还有一类更隐蔽:JSON 能正常解析,业务却悄悄出错。下面六条值得逐条自查。
- 用 JSON.stringify 序列化含 undefined 或函数的对象。错在:undefined 属性和函数会被静默丢弃,不报任何错。接口少传了一个字段,排查半天才发现是序列化时就没了。正确做法:发送前用 Schema 或类型检查确认字段齐全。“无值”用 null 显式表达,不要依赖 undefined。
- 手工拼接字符串生成 JSON。错在:'{"name": "' + name + '"}' 这类写法,一旦变量里带引号、换行或反斜杠,就产出非法 JSON。它同时也是注入攻击的入口。正确做法:一律用 JSON.stringify 或各语言的序列化库生成。需要自定义结构时,先构造对象再序列化。
- 用 === 比较两个 JSON 字符串判断数据是否变化。错在:{"a":1,"b":2} 和 {"b":2,"a":1} 语义完全相同,字符串却不同。缓存与变更检测会误报,空格差异也会触发“假变化”。正确做法:先解析成对象,再做键序无关的深度比较。确需比较文本,先把两边按固定键序 stringify。
- 容忍对象里出现重复键。错在:{"port":8080,"port":9090} 不报错,多数解析器静默取最后一个,另一些实现行为不同。同一份文件在不同环境读出不同结果,这种 bug 能藏几个月。正确做法:在 Schema 或 CI 里加重复键检测。编辑器开启标记重复键的 JSON 校验。
- 忽视文件开头的 UTF-8 BOM。错在:Windows 记事本默认保存会加 BOM(U+FEFF)。JSON.parse 会报 “Unexpected token in JSON at position 0”。这个字符肉眼不可见,很容易误判成“JSON 是好的,是代码有 bug”。正确做法:用“UTF-8 无 BOM”编码保存,VS Code 状态栏可切换。解析前先去掉开头的 \uFEFF。
- 金额用浮点数字段直接传。错在:JSON 的 number 落到 JavaScript 里是 64 位浮点,0.1 + 0.2 !== 0.3。累计、折扣、分摊之后账目对不上,问题通常到对账时才爆发。正确做法:金额以最小单位的整数传输(如分),或用字符串承载精确十进制。展示层再做格式化。