接口返回 JSON 字符串,为什么要再解析一次
调接口时经常遇到这种情况:明明返回的是 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;格式化后某个字段还是一整段带转义的字符串,那就是双重序列化。