JSON.parse()无法将xhr.responseText转换为JS对象问题咨询
问题根源:服务器返回了双重编码的JSON
你遇到的这个问题,核心原因是服务器端对返回的JSON进行了双重编码——简单来说,服务器先把数据转换成了JSON字符串,然后又把这个字符串再次转换成了JSON格式,导致客户端拿到的其实是一个"字符串形式的JSON",而不是原始的JSON数据结构。
具体现象分析
你用alert(xhrResponse)看到的内容是:
"[{\"model\": \"workoutcal.liftactivity\", \"pk\": 1, \"fields\": {\"name\": \"benchpress\"}}]"
注意这个字符串本身被双引号包裹,内部的引号还被转义了。这说明服务器返回的并不是一个数组的JSON,而是一个包含JSON数组的字符串。当你第一次调用JSON.parse(xhrResponse)时,只是把外层的引号和转义去掉,得到的还是那个JSON数组的字符串,所以typeof dbMatches才会显示string。
解决方法
1. 修复服务器端(推荐,从根源解决)
检查服务器的代码,确保只对数据进行一次JSON编码。比如如果是Python/Django后端,不要写成:
# 错误:双重编码 return JsonResponse(json.dumps(data))
而是应该直接返回数据,框架会自动处理JSON编码:
# 正确:单次编码 return JsonResponse(data)
同时确保响应头的Content-Type设置为application/json,这样XHR会自动识别并解析数据,甚至不需要手动调用JSON.parse。
2. 客户端临时补救(不推荐,仅应急)
如果暂时无法修改服务器代码,可以在客户端多调用一次JSON.parse:
var dbMatches = JSON.parse(JSON.parse(xhrResponse)); alert(typeof dbMatches); // 现在会显示object/array
你的代码里还有两个潜在问题需要注意
- 同步XHR请求:你调用
xhr.open("get", url, false)时用了同步模式(第三个参数为false),这会阻塞浏览器主线程,导致页面卡顿,现代浏览器已经不推荐使用同步XHR,建议改成异步模式(第三个参数设为true,这也是默认值)。 this.value的错误引用:在xhr.onreadystatechange回调里,this指向的是XHR对象,而不是触发函数的那个元素,所以this.value会是undefined,导致开头的if (this.value == "")判断完全无效,建议把元素的value提前存到一个变量里:function getDBMatches(){ var inputValue = this.value; // 提前保存当前元素的value var xhr = createXHR(); // ... 其他代码 ... xhr.onreadystatechange = function(){ if (inputValue == ""){ // 用提前保存的变量 return; } // ... 其他逻辑 ... }; // ... 其他代码 ... }
内容的提问来源于stack exchange,提问作者Sahand
相关产品推荐
相关产品推荐

