调一个接口,后端返回的 JSON 前端解析报 Unexpected token } in JSON at position 247。 返回内容是压缩成一行的几千字符 JSON,肉眼根本找不到 position 247 在哪。 我把它粘到 JSON 格式化工具里,展开后一眼看到:有个对象多了个尾随逗号。
JSON 解析报错是开发里的家常便饭,但大多数错误就那么几种。 这篇讲清楚 JSON 的严格语法、5 个最常见的解析错误怎么定位,以及后端 JSON 前端解析失败的常见原因。
JSON 的严格语法(比你以为的严格)
JSON 看起来像 JavaScript 对象,但规则严格得多。这些在 JS 对象里合法,在 JSON 里非法:
- key 不用双引号:JS 里
{name: "张三"}合法,JSON 必须{"name": "张三"} - 单引号字符串:JSON 字符串只能用双引号,
{'a': 1}非法 - 尾随逗号:
{"a": 1,}最后那个逗号在 JSON 里非法 - 注释:JSON 不能写
// 注释或/* */ - 函数 / undefined / 日期对象:JSON 只支持字符串 / 数字 / 布尔 / null / 数组 / 对象
记住:JSON 是数据交换格式,不是代码。它故意比 JS 严格,保证跨语言解析一致。
5 个最常见的 JSON 错误
错误 1:尾随逗号(最常见)
数组或对象的最后一个元素后面多了逗号:数组写成 [1, 2, 3,], 对象写成 {"a": 1, "b": 2,}。
报错:Unexpected token ] / }。 定位:格式化展开后,看报错位置前一个元素的逗号。
错误 2:用了单引号
{'name': '张三'} —— 从 Python 字典 / JS 对象复制过来经常这样。
报错:Unexpected token ' 。 修复:所有单引号换双引号。
错误 3:引号没闭合
字符串少了结尾引号:{"name": "张三, "age": 18}(张三后面少了引号), 解析器把后面的内容都当成字符串的一部分。
报错:位置往往指向后面很远的地方(因为解析器一直在找闭合引号)。 定位:从报错位置往前找最近的未闭合引号。
错误 4:key 没加引号
{name: "张三"} —— 直接从 JS 代码复制的对象。JSON 的 key 必须双引号。
报错:Unexpected token n(指向 key 的第一个字母)。
错误 5:特殊字符没转义
字符串里有未转义的双引号 / 换行 / 反斜杠:{"path": "C:\new"} (反斜杠 + n 被当成换行转义),或者字符串里直接包含真实换行。
修复:双引号转义成 \",反斜杠转义成 \\, 换行转义成 \n。
调试 JSON 的标准流程
- 先格式化:把压缩成一行的 JSON 粘到格式化工具,展开成带缩进的多行
- 看报错位置:工具会高亮出错的行 / 列
- 检查常见错误:报错位置前后找尾随逗号 / 单引号 / 未闭合引号
- 逐层折叠排查:大 JSON 把不相关的层级折叠,缩小排查范围
为什么后端 JSON 前端解析失败
明明后端说返回的是 JSON,前端 JSON.parse 却报错,常见原因:
1. 返回内容前面有杂质
PHP 后端常见:JSON 前面输出了警告信息(Warning: xxx),或者文件开头有 BOM 头。 看返回内容的最前面有没有非 JSON 字符。
2. Content-Type 不对
后端返回的 Content-Type 是 text/html 而不是 application/json, 某些前端框架会因此不解析。
3. 中文编码问题
后端不是 UTF-8 编码,中文变成乱码导致 JSON 结构破坏。 或者中文被转成 \uXXXX 转义序列(这是合法 JSON,解析后还原,不是错误)。
4. 实际返回的是错误页
接口报 500 错误时,服务器可能返回一个 HTML 错误页而不是 JSON。 前端拿到 HTML 去 JSON.parse 当然失败。先看 HTTP 状态码。
JSON 美化 vs 压缩
同一份 JSON 两种形态:
- 美化(格式化):带缩进和换行,人类可读。开发调试用
- 压缩(minify):去掉所有空格换行,体积小 20-50%。接口传输 / 存储用
两者信息完全一样,可以无损互转。开发时看格式化版本,生产传输用压缩版本。
总结
JSON 解析报错 90% 是这 5 种:尾随逗号、单引号、引号没闭合、key 没加引号、特殊字符没转义。 遇到报错先格式化展开,看高亮位置,从常见错误排查。
站里的JSON 格式化工具 支持美化 / 压缩 / 校验 + 错误行列定位 + 折叠层级,纯浏览器本地处理不上传。 如果你的 JSON 里有 Base64 编码的字段看不懂,用Base64 编解码解开看。