jQuery不会从AJAX查询中解析我的JSON


88

我在使用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()函数,它将对它进行完美的评估。

有什么想法我做错了吗?

安东尼


Answers:


72

您的服务器是否以Content-Type发送数据"*/json"?如果不是,请相应地修改响应头。"application/json"例如,发送就可以了。


其次,这个猜测曾经有同样的问题,并且得知我使用了错误的mime类型,这令人惊讶。如果要通过Windows上的localhost测试,请务必注意这一点。尝试将其上传到某个地方,然后再次进行测试。如果您希望它在localhost上运行,则必须对请求进行实际处理。
乔什

51

根据json.org规范,您的返回无效。名称总是用引号引起来,因此您应该返回

{ "title": "One", "key": "1" }

[ { "title": "One", "key": "1" }, { "title": "Two", "key": "2" } ]

这可能不是您的设置的问题,因为您说其中的一个现在可以使用,但是为了确保正确性,应该对其进行修复,以防将来需要切换到另一个JSON解析器。


2
确实,例如在jQuery 1.4中,{ key: 'val' }JSON是无效的。
rfunduk

34

JSON字符串用引号引起来;单引号无效。

{"who": "Hello World"}

是有效的,但这不是...

{'who': 'Hello World'}

尽管不是OP的问题,但对于在此降落的其他人来说,它值得一提。


30

此问题通常是因为您的请求收到了错误的mime类型。在自己的计算机上进行开发时,有时您不会从自己的计算机“服务器”收到正确的mime类型。通过在浏览器中打开本地存储的文件进行开发时,我遇到了这个问题(例如,URL为“ c:/project/test.html”)。

尝试使用beforeSend属性添加一个覆盖mime类型的回调函数。尽管服务器发送了错误的mime类型并通过调用代码接收到了错误的mime类型,但这仍会欺骗代码处理json。下面是一些示例代码。

根据这个问题,正确的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就开始起飞。哇!!谢谢!!
卡门·布莱克

7

我有这个问题,有一段时间我用了

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" );

4
{ 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()不能给您指定是给它一个语句还是一个表达式的方法,并且它容易猜错。

实际上,通常的解决方案是在将任何内容发送到eval()函数之前将其包装在括号中。您说您已经在服务器上尝试过...显然不成功。无论接收到XMLHttpRequest响应是什么,在客户端说的都是防水的:

eval('('+responseText+')');

代替:

eval(responseText);

只要响应确实是表达而不是陈述。(例如,它没有多个以分号或换行符分隔的子句。)


我认为jQuery在处理请求数据时会自动添加括号。
斯特拉格

2
这个答案对我非常有帮助,因为我从不理解人们为什么将JSON括在括号中。
安德烈塔兰佐夫



2

我遇到了类似的问题,Firefox 3.5可以正常工作并解析我的JSON数据,但是Firefox 3.0.6返回了parseerror。原来是JSON开头的空白,导致Firefox 3.0.6抛出错误。删除固定的空白


2

技术“ eval()”和“ JSON.parse()”使用互斥格式。

  • 使用“ eval()”时,必须带括号。
  • 带有“ JSON.parse()”的括号被禁止

当心,有些“ stringify()”函数会产生“ eval”格式。对于ajax,您应该仅使用JSON格式。

尽管“ eval”包含了整个JavaScript语言,但JSON仅使用了该语言的一小部分。在JavaScript语言中,“ eval”必须识别的构造是“ Block语句”(又称“ compound语句”);这是一对或大括号“ {}”,里面带有一些语句。但是在对象文字的语法中也使用花括号。解释通过代码出现的上下文来区分。在您看来,某些东西看起来像对象文字,但“ eval”会将其视为复合语句。

在JavaScript语言中,对象文字出现在分配的右侧。

var myObj = { ...some..code..here... };

对象文字不会单独出现。

{ ...some..code..here... }   // this looks like a compound statement

回到OP在2008年提出的原始问题,他询问为什么以下内容在“ 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的唯一限制。JSONBNF语言规范非常简单。例如,它不允许使用单引号来表示字符串(例如JavaScript和Perl这样做),并且它没有将单个字符表示为字节的方式(例如'C'那样)。不幸的是,它也不允许注释(在创建配置文件时会非常好)。所有这些限制的好处在于,解析JSON的速度很快,并且没有机会进行代码注入(安全威胁)。

由于这些限制,JSON不能用于括号。因此,JSON字符串中的括号是非法字符。

出于以下原因,请始终对ajax使用JSON格式:

  • 将为JSON配置典型的ajax管道。
  • 使用“ eval()”将被批评为安全隐患。

作为ajax管道的示例,请考虑一个涉及Node服务器和jQuery客户端的程序。客户端程序使用形式为的jQuery调用$.ajax({dataType:'json',...etc.});。JQuery创建一个jqXHR对象供以后使用,然后打包并发送关联的请求。服务器接受请求,对其进行处理,然后准备响应。服务器程序将调用该方法res.json(data)以打包并发送响应。回到客户端,jQuery接受响应,查询关联的jqXHR对象,并处理JSON格式的数据。所有这些都不需要手动数据转换。该响应不涉及节点服务器上对JSON.stringify()的显式调用,也不涉及客户端上的JSON.parse()的显式调用。一切都为您完成。

“ eval”的使用与代码注入的安全风险有关。您可能会认为不可能发生,但是黑客可以变得很有创造力。而且,“ eval”对于Javascript优化是有问题的。

如果确实使用“ stringify()”函数来使用,请注意,某些具有该名称的函数将创建与“ eval”而不是与JSON兼容的字符串。例如,在Node中,以下代码为您提供了以“ eval”兼容格式创建字符串的功能:

var stringify = require('node-stringify'); // generates eval() format

这可能很有用,但是除非您有特定需要,否则可能不是您想要的。


1

如果返回数组有效而返回单个对象无效,那么您也可以尝试将单个对象作为包含该单个对象的数组返回:

[ { title: "One", key: "1" } ]

这样,无论数据有效载荷如何,您都将返回一致的数据结构,对象数组。

我发现您已经尝试将单个对象包装在“括号”中,并通过示例提出建议,因为JavaScript与[..]的处理方式不同。


1

如果正在调用jQuery的错误处理程序,并且XHR对象包含“解析器错误”,则可能是服务器发回的解析器错误。

当您在不带参数的情况下调用服务时,是否会出现多结果方案,但是当您尝试提供参数以检索单个记录时,这种情况会中断吗?

您是从哪个后端退回的?

例如,在ASMX服务上,通常将参数作为JSON对象而不是JSON字符串提供给jQuery。如果为jQuery的“数据”参数提供一个实际的JSON对象,它将把它序列化为标准和定界的k,v对,而不是将其作为JSON发送。


1

我发现必须添加一些实现:

obj = new Object; obj = (data.obj);

这似乎解决了问题。不论是否,它似乎对我来说完全一样。


初始化新对象时,请使用对象文字,而不要使用Object构造函数:var obj = {};
安德烈亚斯·格雷奇

是的,我知道了,var myArray = []用于数组,var myObject = {},感谢技巧Dreas
Jay

1

jQuery在某些JSON键上令人窒息。我正在用PHP发送此JSON代码段:

echo json_encode((object) array('result' => 'success'));

将“结果”键重命名为其他功能。我想这是某种保留字冲突,可能是jQuery(1.4.2)中的错误。


1

在ColdFusion环境中,即使使用格式正确的JSON,也将导致错误的一件事是,在ColdFusion管理器中打开了“ 启用请求调试输出”(在“调试和日志记录”>“调试输出设置”下)。调试信息将与JSON数据一起返回,因此将使其无效。


1

也试试这个

$.ajax({
    url: url,
    data:datas,
    success:function(datas, textStatus, jqXHR){
    var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('{')));
})};

在我的情况下,服务器以“ {”之前的未知字符响应


1

我正在获取状态= parseerror和xhr.status = 200。

对我来说,问题是JSON响应中的URL已将“ \”切换为“ /”,从而解决了此问题。


0

我为此苦苦挣扎,花了几个小时试图弄清楚这一点,直到我使用萤火虫显示数据对象。

var data = eval("(" + data.responseText + ")");
console.log(data.count);

-1

$data = yourarray(); 
json_encode($data)

在服务器端。在客户端,将ajax与数据类型JSON一起使用,并确保您的文档编码不是带有BOM的UTF-8,它必须是UTF-8。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.