JQuery 不会从 AJAX 查询解析我的 JSON

我在使用 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" }

调用 error 函数,xhr 包含“ parsererror”。我试过在发送之前在服务器上用括号将 JSON 包装起来,但是没有什么区别。然而,如果我用 Javascript 将内容粘贴到一个字符串中,然后使用 eval ()函数,它会完美地计算它。

知道我哪里做错了吗?

安东尼

205460 次浏览

Is your server sending data as Content-Type "*/json"? If not, modify the response headers accordingly. Sending "application/json" would be fine, for example.

This problem is usually because your request received the wrong mime type. When developing on your own computer, sometimes you are not receiving the proper mime type from the "server", which is your own computer. I ran into this problem once when developing by opening the locally stored file in the browser (e.g. the url was "c:/project/test.html").

Try using the beforeSend property to add a callback function that overrides the mime type. This will trick the code into dealing with json despite the wrong mime type being sent by the server and received by your calling code. Some example code is below.

The proper mime type is application/json according to this question, but I do know that application/j-son worked when I tried it (now several years ago). You should probably try application/json first.

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...
}
});

If returning an array works and returning a single object doesn't, you might also try returning your single object as an array containing that single object:

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

that way you are returning a consistent data structure, an array of objects, no matter the data payload.

i see that you've tried wrapping your single object in "parenthesis", and suggest this with example because of course JavaScript treats [ .. ] differently than ( .. )

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

Is not what you think. As an expression, it's an Object literal, but as a statement, it's:

{                // 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

Unfortunately eval() does not give you a way to specify whether you are giving it a statement or an expression, and it tends to guess wrong.

The usual solution is indeed to wrap anything in parentheses before sending it to the eval() function. You say you've tried that on the server... clearly somehow that isn't getting through. It should be waterproof to say on the client end, whatever is receiving the XMLHttpRequest response:

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

instead of:

eval(responseText);

as long as the response is really an expression not a statement. (eg. it doesn't have multiple, semicolon-or-newline-separated clauses.)

According to the json.org specification, your return is invalid. The names are always quoted, so you should be returning

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

and

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

This may not be the problem with your setup, since you say one of them works now, but it should be fixed for correctness in case you need to switch to another JSON parser in the future.

If jQuery's error handler is being called and the XHR object contains "parser error", that's probably a parser error coming back from the server.

Is your multiple result scenario when you call the service without a parameter, but it's breaking when you try to supply a parameter to retrieve the single record?

What backend are you returning this from?

On ASMX services, for example, that's often the case when parameters are supplied to jQuery as a JSON object instead of a JSON string. If you provide jQuery an actual JSON object for its "data" parameter, it will serialize that into standard & delimited k,v pairs instead of sending it as JSON.

I found in some of my implementations I had to add:

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

which seemed to solve the problem. Eval or not it seemed to do exactly the same for me.

If you are consuming ASP.NET Web Services using jQuery, make sure you have the following included in your web.config:

<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>

I had a similar problem to this where Firefox 3.5 worked fine and parsed my JSON data but Firefox 3.0.6 returned a parseerror. Turned out it was a blank space at the start of the JSON that caused Firefox 3.0.6 to throw an error. Removing the blank space fixed it

JSON strings are wrapped in double quotes; single quotes are not a valid substitute.

{"who": "Hello World"}

is valid but this is not...

{'who': 'Hello World'}

Whilst not the OP's issue, thought it worth noting for others who land here.

I had this issue and for a bit I used

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

to get the data returned in an object. but then later had other issues getting a 'missing ) in parenthetical' error and found out that jQuery has a function specifically for evaluating a string for a json structure:

$.parseJSON(data)

should do the trick. This is in addition to having your json string in the proper format of course..

jQuery chokes on certain JSON keys. I was sending this JSON snippet in PHP:

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

Renaming the 'result' key to something else works. I would guess this is a reserved word collision of some kind, and could be a bug in jQuery (1.4.2).

In a ColdFusion environment, one thing that will cause an error, even with well-formed JSON, is having Enable Request Debugging Output turned on in the ColdFusion Administrator (under Debugging & Logging > Debug Output Settings). Debugging information will be returned with the JSON data and will thus make it invalid.

I was struggling with this, and spent a few hours trying to figure this out, until I used firebug to show the data object.

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

also try this

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

in my case server responds with unknow character before '{'

If you are echoing out the json response and your headers don't match */json then you can use the built in jQuery.parseJSON api to parse the response.

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );

I was getting status = parseerror and xhr.status = 200.

The issue for me was the URL's inside the JSON response had '\' switching to '/' fixed this.

use

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

on server side. On client side use ajax with Datatype JSON and be sure your document encoding is not UTF-8 with BOM it has to be UTF-8.

You will to have to set header content type in your php like this:

 <?php


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


?>

Watch these Video for better understanding....

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

The techniques "eval()" and "JSON.parse()" use mutually exclusive formats.

  • With "eval()" parenthesis are required.
  • With "JSON.parse()" parenthesis are forbidden.

Beware, there are "stringify()" functions that produce "eval" format. For ajax, you should use only the JSON format.

While "eval" incorporates the entire JavaScript language, JSON uses only a tiny subset of the language. Among the constructs in the JavaScript language that "eval" must recognize is the "Block statement" (a.k.a. "compound statement"); which is a pair or curly braces "{}" with some statements inside. But curly braces are also used in the syntax of object literals. The interpretation is differentiated by the context in which the code appears. Something might look like an object literal to you, but "eval" will see it as a compound statement.

In the JavaScript language, object literals occur to the right of an assignment.

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

Object literals don't occur on their own.

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

Going back to the OP's original question, asked in 2008, he inquired why the following fails in "eval()":

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

The answer is that it looks like a compound statement. To convert it into an object, you must put it into a context where a compound statement is impossible. That is done by putting parenthesis around it

( { title: "One", key: "1" } )    // not a compound statment, so must be object literal

The OP also asked why a similar statement did successfully eval:

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

The same answer applies -- the curly braces are in a context where a compound statement is impossible. This is an array context, "[...]", and arrays can contain objects, but they cannot contain statements.

Unlike "eval()", JSON is very limited in its capabilities. The limitation is intentional. The designer of JSON intended a minimalist subset of JavaScript, using only syntax that could appear on the right hand side of an assignment. So if you have some code that correctly parses in JSON...

var myVar = JSON.parse("...some...code...here...");

...that implies it will also legally parse on the right hand side of an assignment, like this..

var myVar = ...some..code..here... ;

But that is not the only restriction on JSON. The BNF language specification for JSON is very simple. For example, it does not allow for the use of single quotes to indicate strings (like JavaScript and Perl do) and it does not have a way to express a single character as a byte (like 'C' does). Unfortunately, it also does not allow comments (which would be really nice when creating configuration files). The upside of all those limitations is that parsing JSON is fast and offers no opportunity for code injection (a security threat).

Because of these limitations, JSON has no use for parenthesis. Consequently, a parenthesis in a JSON string is an illegal character.

Always use JSON format with ajax, for the following reasons:

  • A typical ajax pipeline will be configured for JSON.
  • The use of "eval()" will be criticised as a security risk.

As an example of an ajax pipeline, consider a program that involves a Node server and a jQuery client. The client program uses a jQuery call having the form $.ajax({dataType:'json',...etc.});. JQuery creates a jqXHR object for later use, then packages and sends the associated request. The server accepts the request, processes it, and then is ready to respond. The server program will call the method res.json(data) to package and send the response. Back at the client side, jQuery accepts the response, consults the associated jqXHR object, and processes the JSON formatted data. This all works without any need for manual data conversion. The response involves no explicit call to JSON.stringify() on the Node server, and no explicit call to JSON.parse() on the client; that's all handled for you.

The use of "eval" is associated with code injection security risks. You might think there is no way that can happen, but hackers can get quite creative. Also, "eval" is problematic for Javascript optimization.

If you do find yourself using a using a "stringify()" function, be aware that some functions with that name will create strings that are compatible with "eval" and not with JSON. For example, in Node, the following gives you function that creates strings in "eval" compatible format:

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

This can be useful, but unless you have a specific need, it's probably not what you want.