jQuery 不会从 AJAX 查询中解析我的 JSON
Posted
技术标签:
【中文标题】jQuery 不会从 AJAX 查询中解析我的 JSON【英文标题】:jQuery won't parse my JSON from AJAX query 【发布时间】:2010-09-19 23:10:37 【问题描述】:我在使用 jQuery.ajax() 解析从我的服务器返回的一些 JSON 数据时遇到困难
要执行我正在使用的 AJAX:
$.ajax(
url: myUrl,
cache: false,
dataType: "json",
success: function(data)
...
,
error: function(e, xhr)
...
);
如果我返回一个项目数组,那么它工作正常:
[ title: "One", key: "1" , title: "Two", key: "2" ]
调用成功函数并接收正确的对象。
但是,当我尝试返回单个对象时:
title: "One", key: "1"
错误函数被调用并且 xhr 包含“parsererror”。在将它发送到网络之前,我已经尝试将 JSON 包装在服务器上的括号中,但这没有任何区别。然而,如果我将内容粘贴到 javascript 中的字符串中,然后使用 eval() 函数,它会完美地评估它。
任何想法我做错了什么?
安东尼
【问题讨论】:
相关:***.com/questions/631418/… 【参考方案1】:您的服务器是否以 Content-Type "*/json"
发送数据?如果不是,请相应地修改响应标头。例如,发送"application/json"
就可以了。
【讨论】:
第二次猜测,曾经遇到过同样的问题,但令人惊讶的是我使用了错误的 mime 类型。如果您在 Windows 上通过 localhost 进行测试,请务必注意这一点。尝试将其上传到某个地方并再次测试。如果你想让它在 localhost 上工作,你必须真正捏造请求。【参考方案2】:根据json.org 规范,您的退货无效。名称总是被引用,所以你应该返回
"title": "One", "key": "1"
和
[ "title": "One", "key": "1" , "title": "Two", "key": "2" ]
这可能不是您的设置问题,因为您说其中一个现在可以工作,但应该修复它以确保正确性,以防您将来需要切换到另一个 JSON 解析器。
【讨论】:
确实,在 jQuery 1.4 中(例如) key: 'val'
不是有效的 JSON。【参考方案3】:
JSON 字符串用 双 引号括起来;单引号不是有效的替代品。
"who": "Hello World"
有效,但这不是...
'who': 'Hello World'
虽然不是 OP 的问题,但认为对于登陆这里的其他人来说值得注意。
【讨论】:
【参考方案4】:这个问题通常是因为您的请求收到了错误的 mime 类型。在您自己的计算机上开发时,有时您无法从“服务器”(即您自己的计算机)接收到正确的 mime 类型。我在开发时通过在浏览器中打开本地存储的文件时遇到了这个问题(例如,url是“c:/project/test.html”)。
尝试使用 beforeSend 属性添加一个覆盖 mime 类型的回调函数。尽管服务器发送了错误的 mime 类型并由您的调用代码接收,这将诱使代码处理 json。下面是一些示例代码。
根据this question,正确的 mime 类型是 application/json,但我确实知道 application/j-son 在我尝试时有效(现在是几年前)。你应该先试试 application/json。
var jsonMimeType = "application/json;charset=UTF-8";
$.ajax(
type: "GET",
url: myURL,
beforeSend: function(x)
if(x && x.overrideMimeType)
x.overrideMimeType(jsonMimeType);
,
dataType: "json",
success: function(data)
// do stuff...
);
【讨论】:
只想说你建议的 beforeSend 建议对我有用!我的 ajax 调用在 safari 和 chrome 中效果很好,但在 firefox 中效果不佳。一旦我添加了 beforeSend 然后 Firefox 就起飞了。哇!!谢谢!!【参考方案5】:我遇到了这个问题,我用了一段时间
eval('('+data+')')
获取对象中返回的数据。但后来又遇到了其他问题,在括号中出现“缺少 )”错误,并发现 jQuery 有一个专门用于评估 json 结构的字符串的函数:
$.parseJSON(data)
应该可以解决问题。这当然是除了让你的 json 字符串以正确的格式之外..
【讨论】:
【参考方案6】:如果您正在回显 json 响应并且您的标头与 */json 不匹配,那么您可以使用内置的 jQuery.parseJSON api 来解析响应。
response = '"name":"John"';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );
【讨论】:
【参考方案7】: title: "One", key: "1"
不是你想的那样。作为一个表达式,它是一个 Object 字面量,但作为一个语句,它是:
// new block
title: // define a label called 'title' for goto statements
"One", // statement: the start of an expression which will be ignored
key: // ...er, what? you can't have a goto label in the middle of an expression
// ERROR
不幸的是 eval() 没有给你一个方法来指定你是给它一个语句还是一个表达式,它往往会猜错。
通常的解决方案确实是在将 anything 发送到 eval() 函数之前将其包裹在括号中。你说你已经在服务器上试过了......显然不知何故没有通过。在客户端应该是防水的,无论接收到 XMLHttpRequest 响应:
eval('('+responseText+')');
代替:
eval(responseText);
只要响应确实是表达式而不是语句。 (例如,它没有多个分号或换行符分隔的子句。)
【讨论】:
我认为jQuery在处理请求数据时会自动添加括号。 这个答案对我很有帮助,因为我一直不明白为什么人们将 JSON 包裹在括号中。【参考方案8】:您必须像这样在您的 php 中设置标题内容类型:
<?php
header('Content-type:application/json');
?>
观看这些视频以更好地理解....
参考:http://www.youtube.com/watch?v=EvFXWqEqh6o
【讨论】:
【参考方案9】:如果您使用 jQuery 使用 ASP.NET Web 服务,请确保您的 web.config 中包含以下内容:
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
【讨论】:
【参考方案10】:我遇到了与此类似的问题,Firefox 3.5 运行良好并解析了我的 JSON 数据,但 Firefox 3.0.6 返回了一个 parseerror。原来是 JSON 开头的空格导致 Firefox 3.0.6 抛出错误。删除空格修复它
【讨论】:
【参考方案11】:“eval()”和“JSON.parse()”技术使用互斥格式。
带有“eval()”括号是必需的。 禁止使用“JSON.parse()”括号。请注意,有些“stringify()”函数会产生“eval”格式。对于 ajax,您应该只使用 JSON 格式。
虽然“eval”包含整个 JavaScript 语言,但 JSON 仅使用该语言的一小部分。在 JavaScript 语言中,“eval”必须识别的结构是"Block statement" (a.k.a. "compound statement");这是一对或花括号“”,里面有一些语句。但是花括号也用于对象字面量的语法中。解释因代码出现的上下文而异。有些东西对您来说可能看起来像一个对象字面量,但“eval”会将它视为复合语句。
在 JavaScript 语言中,对象字面量出现在赋值的右侧。
var myObj = ...some..code..here... ;
对象字面量不会单独出现。
...some..code..here... // this looks like a compound statement
回到 2008 年提出的 OP 的原始问题,他询问为什么“eval()”中出现以下错误:
title: "One", key: "1"
答案是它看起来像一个复合语句。要将其转换为对象,您必须将其放入无法使用复合语句的上下文中。这是通过在它周围加上括号来完成的
( title: "One", key: "1" ) // not a compound statment, so must be object literal
OP 还询问为什么类似的语句确实成功评估:
[ title: "One", key: "1" , title: "Two", key: "2" ]
同样的答案也适用——花括号是在复合语句不可能的上下文中。这是一个数组上下文,“[...]
”,数组可以包含对象,但不能包含语句。
与“eval()”不同,JSON 的功能非常有限。限制是故意的。 JSON 的设计者想要一个极简的 JavaScript 子集,只使用可能出现在赋值右侧的语法。因此,如果您有一些可以正确解析为 JSON 的代码...
var myVar = JSON.parse("...some...code...here...");
...这意味着它也将在分配的右侧合法地解析,就像这样..
var myVar = ...some..code..here... ;
但这并不是对 JSON 的唯一限制。 BNF language specification for JSON 非常简单。例如,它不允许使用单引号来表示字符串(就像 JavaScript 和 Perl 那样),并且它没有办法将单个字符表示为一个字节(就像 'C' 那样)。不幸的是,它也不允许 cmets(这在创建配置文件时非常好)。所有这些限制的好处是解析 JSON 速度很快,并且没有提供代码注入的机会(安全威胁)。
由于这些限制,JSON 不能使用括号。因此,JSON 字符串中的括号是非法字符。
始终使用带有 ajax 的 JSON 格式,原因如下:
将为 JSON 配置一个典型的 ajax 管道。 使用“eval()”将被批评为安全风险。作为 ajax 管道的示例,考虑一个涉及 Node 服务器和 jQuery 客户端的程序。客户端程序使用格式为$.ajax(dataType:'json',...etc.);
的jQuery 调用。 JQuery 创建一个 jqXHR 对象供以后使用,然后打包并发送关联的请求。服务器接受请求,处理它,然后准备响应。服务端程序会调用res.json(data)
方法打包并发送响应。回到客户端,jQuery 接受响应,查询相关的 jqXHR 对象,并处理 JSON 格式的数据。这一切都不需要手动数据转换。响应不涉及在 Node 服务器上对 JSON.stringify() 的显式调用,也没有在客户端对 JSON.parse() 的显式调用;这一切都为您处理。
使用“eval”会带来代码注入安全风险。您可能认为不可能发生这种情况,但黑客可以非常有创意。此外,“eval”对于 Javascript 优化也是有问题的。
如果您确实使用“stringify()”函数,请注意某些具有该名称的函数将创建与“eval”兼容而不与 JSON 兼容的字符串。例如,在 Node 中,以下为您提供了以“eval”兼容格式创建字符串的函数:
var stringify = require('node-stringify'); // generates eval() format
这可能很有用,但除非您有特定需求,否则可能不是您想要的。
【讨论】:
【参考方案12】:如果返回数组有效而返回单个对象无效,您也可以尝试将单个对象作为包含该单个对象的数组返回:
[ title: "One", key: "1" ]
这样,无论数据负载如何,您都将返回一致的数据结构、对象数组。
我看到您已经尝试将单个对象包装在“括号”中,并通过示例提出建议,因为 JavaScript 对 [..] 的处理方式与 (..) 不同
【讨论】:
【参考方案13】:如果正在调用 jQuery 的错误处理程序并且 XHR 对象包含“解析器错误”,则可能是从服务器返回的解析器错误。
当您在没有参数的情况下调用服务时,您的多重结果场景是否会在您尝试提供参数来检索单个记录时中断?
你从哪个后端返回这个?
例如,在 ASMX 服务上,当参数作为 JSON 对象而不是 JSON 字符串提供给 jQuery 时,通常会出现这种情况。如果您为 jQuery 的“数据”参数提供一个实际的 JSON 对象,它会将其序列化为标准和分隔的 k,v 对,而不是将其作为 JSON 发送。
【讨论】:
【参考方案14】:我发现在我的一些实现中我必须添加:
obj = new Object; obj = (data.obj);
这似乎解决了问题。评估与否对我来说似乎完全一样。
【讨论】:
在初始化新对象时使用对象字面量,而不是 Object 构造函数:var obj = ; 是的,我明白了,var myArray = [] 用于数组和 var myObject = ,感谢 Dreas 的提示【参考方案15】:jQuery 在某些 JSON 键上阻塞。我正在用 PHP 发送这个 JSON sn-p:
echo json_encode((object) array('result' => 'success'));
将“结果”键重命名为其他名称有效。我猜这是某种保留字冲突,可能是 jQuery (1.4.2) 中的错误。
【讨论】:
【参考方案16】:在 ColdFusion 环境中,即使使用格式正确的 JSON,也会导致错误的一件事是在 ColdFusion 管理器中启用启用请求调试输出(在调试和日志记录 > 调试输出下)设置)。调试信息将与 JSON 数据一起返回,从而使其无效。
【讨论】:
【参考方案17】:也试试这个
$.ajax(
url: url,
data:datas,
success:function(datas, textStatus, jqXHR)
var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('')));
);
在我的情况下,服务器在“”之前以未知字符响应
【讨论】:
【参考方案18】:我得到了 status = parseerror 和 xhr.status = 200。
对我来说,问题是 JSON 响应中的 URL 将“\”切换到“/”解决了这个问题。
【讨论】:
【参考方案19】:我为此苦苦挣扎,花了几个小时试图弄清楚这一点,直到我使用 firebug 来显示数据对象。
var data = eval("(" + data.responseText + ")");
console.log(data.count);
【讨论】:
【参考方案20】:使用
$data = yourarray();
json_encode($data)
在服务器端。 在客户端 使用带有数据类型 JSON 的 ajax,并确保您的文档编码不是带有 BOM 的 UTF-8,它必须是 UTF-8。
【讨论】:
以上是关于jQuery 不会从 AJAX 查询中解析我的 JSON的主要内容,如果未能解决你的问题,请参考以下文章
使用 JSON 从 AJAX 和 JQuery 调用简单的 Web 服务(.asmx 文件) - 解析错误
dataType json 的 jQuery $.ajax 请求不会从 PHP 脚本中检索数据