jQuery won't parse my JSON from AJAX query

2019-01-01 12:45发布

问题:

I\'m having difficulty parsing some JSON data returned from my server using jQuery.ajax()

To perform the AJAX I\'m using:

$.ajax({
  url: myUrl,
  cache: false,
  dataType: \"json\",
  success: function(data){
    ...
  },
  error: function(e, xhr){
    ...
  }
});  

And if I return an array of items then it works fine:

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

The success function is called and receives the correct object.

However, when I\'m trying to return a single object:

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

The error function is called and xhr contains \'parsererror\'. I\'ve tried wrapping the JSON in parenthesis on the server before sending it down the wire, but it makes no difference. Yet if I paste the content into a string in Javascript and then use the eval() function, it evaluates it perfectly.

Any ideas what I\'m doing wrong?

Anthony

回答1:

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



回答2:

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.



回答3:

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.



回答4:

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


回答5:

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..



回答6:

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


回答7:

{ 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.)



回答8:

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>


回答9:

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



回答10:

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



回答11:

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.



回答12:

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 ( .. )



回答13:

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.



回答14:

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.



回答15:

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



回答16:

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.



回答17:

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 \'{\'



回答18:

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.



回答19:

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


回答20:

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.



标签: jquery ajax json