"Unexpected token"、"Unexpected end of input"——几乎每个写过接口的开发者都见过这类 JSON 解析错误。它们看着吓人,但背后的原因其实相当有限,而且高度可预测。绝大多数无效 JSON 都不是格式本身有多深奥,而是某个看不见的字符、某段错误的字符串拼接,或者某处编码不一致在作祟。学会按图索骥地排查,能把这类问题从"玄学"变成"例行公事"。
先确认你拿到的到底是不是 JSON
解析失败时,第一步永远是看原始响应体本身,而不是先去怀疑解析器。很多时候你以为收到的是 JSON,实际却是一段 HTML 错误页、一个空字符串,或者一段带前缀的文本。把响应原样打印出来,你常常会发现根本不是格式问题,而是上游返回了完全不同的东西。
检查 Content-Type 头也很有帮助:如果它不是 application/json,那大概率说明请求走错了路径,或者命中了某个错误处理分支。
当心看不见的字符
有一类故障特别折磨人:JSON 肉眼看上去完全正确,解析器却坚持报错。罪魁祸首往往是不可见字符——文件开头的 BOM、混进字符串里的控制字符,或者从富文本里复制粘贴带进来的特殊空白。这些字符在普通编辑器里看不见,却能让严格的解析器直接拒绝。
遇到"看着没问题却解析不了"的情况,用十六进制视图或专门的工具检查字节,常常一眼就能揪出那个潜伏的字符。
字符串拼接是头号元凶
最常见的无效 JSON,来自手动拼字符串构造 JSON。一旦数据里出现引号、反斜杠或换行,未经转义就直接拼进去,结构立刻就破了。用户输入里一个意外的双引号,就足以让整段 JSON 失效。
解决办法几乎总是同一个:不要手写 JSON,改用语言内建的序列化函数。让序列化器去处理转义,能从根上消除一大类故障。如果你正在手动拼接 JSON,那通常就是该重构的信号。
编码不一致带来的乱码
JSON 标准要求使用 UTF-8。当数据在某一环节以另一种编码被读取或写入时,多字节字符就会变成乱码,进而破坏结构或产生无效序列。这类问题在跨系统传输、读取老文件或对接遗留服务时尤其常见。
排查时,确认从产生 JSON 到消费 JSON 的整条链路都统一使用 UTF-8。在每道边界上核对编码声明,往往就能定位到那个转换出错的环节。
那些"宽松"语法其实是陷阱
很多人写 JSON 时会不自觉地带上一些 JavaScript 习惯:末尾多一个逗号、用单引号包字符串、键名不加引号、写注释。这些在某些环境里能用,但严格的 JSON 标准一概不允许。当你的数据流过一个严格解析器时,它们就会变成解析错误。
记住 JSON 的语法比看上去更克制:键必须用双引号,不能有尾逗号,不能有注释。如果你需要注释或更宽松的语法,那说明你要的可能是配置格式而非数据交换格式。
把错误信息当作线索
解析器报的错往往附带位置信息,比如出错的行号或字符偏移量。别忽略它——直接跳到那个位置,问题通常就在附近。"Unexpected end of input"多半意味着响应被截断或为空;"Unexpected token"则常指向某处转义或拼接错误。
把这些线索和前面的检查结合起来:先看原始字节,再查编码,再查拼接方式。沿着这条思路,绝大多数 JSON 解析错误都能被快速、可靠地定位并修复,而不必凭运气瞎猜。