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 文件) - 解析错误

如何解决jquery“解析器错误”

在jQuery ajax json响应中解析iso日期

dataType json 的 jQuery $.ajax 请求不会从 PHP 脚本中检索数据

我在 ajax 成功接收我的数据如何在表中显示 jquery 数据

jQuery Ajax详解