调接口时经常遇到这种情况:明明返回的是 JSON,取字段却报 undefined,打印出来发现整个响应是一个字符串。

不是接口坏了,是它被序列化了两次。

HTTP 传的都是文本

不管 Content-Type 写的是 application/json 还是别的,网络上跑的都是字节流。

fetch 的 response.json()、axios 的自动转换、Java 的 @ResponseBody,都是在你拿到文本之后做了一次 parse。所以你平时看到的“对象”,是客户端库帮你转好的。

双重序列化怎么发生

后端某个字段本身就是一段 JSON 字符串,比如 "extra": "{\"a\":1}"。

整个响应序列化一次,这个字段被当成普通字符串又转义了一次。前端 parse 完最外层,extra 仍然是字符串,还得再 parse 一次。

另一种情况:网关或日志组件把响应体当字符串处理,包了一层再返回。

怎么判断

打印 typeof data。是 string,说明还得 parse。

typeof data.extra 也是同理。字段值以 { 或 [ 开头、以 } 或 ] 结尾,大概率是 JSON 字符串。

怎么处理

先判断类型再解析,别无条件 parse:

const extra = typeof data.extra === 'string' ? JSON.parse(data.extra) : data.extra

包一层 try/catch,防止字段为空或格式不对时整个流程崩掉。

更根本的解法是让后端别双重序列化。字段该是对象就是对象,别先 stringify 再塞进响应。

排查工具

不确定那一层到底是什么,把响应原文贴进 JSON 在线解析工具。能格式化说明是合法 JSON;格式化后某个字段还是一整段带转义的字符串,那就是双重序列化。