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() 函数,它会完美地评估它。

任何想法我做错了什么?

安东尼

4

20 回答 20

72

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

于 2008-10-30T10:29:13.347 回答
52

根据json.org规范,您的退货无效。名称总是被引用,所以你应该回来

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

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

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

于 2008-10-30T17:45:49.157 回答
34

JSON 字符串用引号括起来;单引号不是有效的替代品。

{"who": "Hello World"}

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

{'who': 'Hello World'}

虽然不是 OP 的问题,但认为对于登陆这里的其他人来说值得注意。

于 2010-03-25T22:45:12.097 回答
30

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

尝试使用 beforeSend 属性添加一个覆盖 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...
 }
});
于 2008-10-30T13:56:24.580 回答
7

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

eval('('+data+')')

获取对象中返回的数据。但后来又遇到了其他问题,在括号中出现“缺少 )”错误,并发现 jQuery 有一个专门用于评估 json 结构的字符串的函数:

$.parseJSON(data)

应该做的伎俩。这当然是除了让你的 json 字符串以正确的格式之外..

于 2010-12-16T21:55:52.180 回答
6

如果您正在回显 json 响应并且您的标头与 */json 不匹配,那么您可以使用内置的 jQuery.parseJSON api 来解析响应。

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );
于 2012-05-16T22:44:00.377 回答
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);

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

于 2008-10-30T14:24:38.003 回答
3

您必须在 php 中设置标题内容类型,如下所示:

 <?php

 header('Content-type:application/json');

 ?>

观看这些视频以更好地理解......

参考:http ://www.youtube.com/watch?v=EvFXWqEqh6o

于 2014-07-27T04:59:34.467 回答
2

如果您使用 jQuery 使用 ASP.NET Web 服务,请确保您的 web.config 中包含以下内容:

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>
于 2008-12-08T21:05:25.097 回答
2

我遇到了与此类似的问题,其中 Firefox 3.5 运行良好并解析了我的 JSON 数据,但 Firefox 3.0.6 返回了一个 parseerror。原来是 JSON 开头的空格导致 Firefox 3.0.6 抛出错误。删除空格修复了它

于 2010-01-27T11:52:03.053 回答
2

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

  • 带有“eval()”括号是必需的。
  • 禁止使用“JSON.parse()”括号。

请注意,有“stringify()”函数会产生“eval”格式。对于 ajax,您应该只使用 JSON 格式。

虽然“eval”包含了整个 JavaScript 语言,但 JSON 只使用了该语言的一小部分。在 JavaScript 语言中,“eval”必须识别的结构是“块语句”(又名“复合语句”);这是一对或花括号“{}”,里面有一些语句。但是花括号也用于对象字面量的语法中。解释因代码出现的上下文而异。有些东西对您来说可能看起来像一个对象字面量,但“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 的唯一限制。JSON的BNF 语言规范非常简单。例如,它不允许使用单引号来表示字符串(就像 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 格式的数据。这一切都不需要手动数据转换。响应不涉及在 Node 服务器上对 JSON.stringify() 的显式调用,也没有在客户端对 JSON.parse() 的显式调用;这一切都为你处理。

“eval”的使用与代码注入安全风险有关。您可能认为不可能发生这种情况,但黑客可以非常有创意。此外,“eval”对于 Javascript 优化也是有问题的。

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

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

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

于 2016-11-13T00:14:53.393 回答
1

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

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

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

我看到您已尝试将单个对象包装在“括号”中,并通过示例提出此建议,因为当然 JavaScript 对待 [ .. ] 与 ( .. ) 不同

于 2008-10-30T14:17:19.937 回答
1

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

当您在没有参数的情况下调用服务时,您的多重结果场景是否存在,但是当您尝试提供参数来检索单个记录时它会中断?

你从哪个后端返回这个?

例如,在 ASMX 服务上,当参数作为 JSON 对象而不是 JSON 字符串提供给 jQuery 时,通常会出现这种情况。如果你为 jQuery 提供一个实际的 JSON 对象作为它的“data”参数,它会将它序列化成标准的 & 分隔的 k,v 对,而不是作为 JSON 发送。

于 2008-11-28T04:48:05.977 回答
1

我发现在我的一些实现中我必须添加:

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

这似乎解决了这个问题。评估与否,它似乎对我来说完全一样。

于 2008-11-29T16:01:01.050 回答
1

jQuery 阻塞某些 JSON 键。我在 PHP 中发送了这个 JSON 片段:

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

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

于 2011-01-07T23:34:30.673 回答
1

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

于 2011-04-04T17:40:16.197 回答
1

也试试这个

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

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

于 2012-04-06T13:22:56.803 回答
1

我得到了 status = parseerror 和 xhr.status = 200。

对我来说,问题是 JSON 响应中的 URL 有 '\' 切换到 '/' 解决了这个问题。

于 2014-04-23T14:20:15.377 回答
0

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

var data = eval("(" + data.responseText + ")");
console.log(data.count);
于 2011-04-29T23:50:45.950 回答
-1

采用

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

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

于 2014-07-22T10:53:11.630 回答