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

有什么想法我做错了什么吗?

安东尼


相关:https://dev59.com/unRB5IYBdhLWcg3wa2m2 - Michael Myers
20个回答

72

你的服务器是否将数据发送为Content-Type "*/json"?如果不是,请相应地修改响应头。比如发送"application/json"即可。


赞同这个猜测,我曾经遇到过同样的问题,并且发现令人惊讶的是我使用了错误的MIME类型。如果您在Windows上通过localhost进行测试,请非常注意此问题。尝试将其上传到其他位置并再次进行测试。如果您希望它在localhost上运行,则必须真正地伪造请求。 - Josh

52
根据 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'}

虽然这不是提问者的问题,但对于其他来到这里的人可能值得注意。


30

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

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

根据此问题,正确的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就立刻起飞了。哇!!谢谢!! - Karmen Blake

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" }

这并不是你想象中的那样。作为一个表达式,它是一个对象字面量,但作为一个语句,它是:

{                // 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在处理请求数据时会自动添加括号。 - strager
2
这个答案对我非常有帮助,因为我从来没有理解为什么人们要在 JSON 中加括号。 - Andrey Tarantsov

3

您需要在php中设置头部内容类型,例如:

 <?php

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

 ?>

为了更好地理解,请观看以下视频...

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


2
如果您正在使用jQuery消费ASP.NET Web服务,请确保在您的web.config中包含以下内容:
<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>

2

我曾经遇到过类似的问题,Firefox 3.5 可以正常解析我的 JSON 数据,但是 Firefox 3.0.6 却返回了一个 parseerror。后来发现是 JSON 数据开头有一个空格导致 Firefox 3.0.6 报错。删除这个空格就解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接