Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Make sure that a parsererror is thrown whenever malformed JSON comes …

…back from a server (so that the Ajax error handler is called). Makes it uniform across browsers that do and don't have JSON.parse support.
  • Loading branch information...
commit 308d6cdad023da190ace2a698ee4815ed8dad9c5 1 parent c14fa51
John Resig authored January 07, 2010
18  src/ajax.js
@@ -570,20 +570,26 @@ jQuery.extend({
570 570
 
571 571
 		// The filter can actually parse the response
572 572
 		if ( typeof data === "string" ) {
573  
-			// If the type is "script", eval it in global context
574  
-			if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
575  
-				jQuery.globalEval( data );
576  
-			}
577  
-
578 573
 			// Get the JavaScript object, if JSON is used.
579 574
 			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
580 575
 				// Try to use the native JSON parser first
581 576
 				if ( window.JSON && window.JSON.parse ) {
582 577
 					data = window.JSON.parse( data );
583 578
 
  579
+				// Make sure the incoming data is actual JSON
  580
+				// Logic borrowed from http://json.org/json2.js
  581
+				} else if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
  582
+					.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
  583
+					.replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
  584
+						data = (new Function("return " + data))();
  585
+
584 586
 				} else {
585  
-					data = (new Function("return " + data))();
  587
+					throw "JSON Syntax Error: " + data;
586 588
 				}
  589
+
  590
+			// If the type is "script", eval it in global context
  591
+			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
  592
+				jQuery.globalEval( data );
587 593
 			}
588 594
 		}
589 595
 
1  test/data/badjson.js
... ...
@@ -0,0 +1 @@
  1
+{bad: 1}
23  test/unit/ajax.js
@@ -341,13 +341,13 @@ test("jQuery.param()", function() {
341 341
 
342 342
 test("synchronous request", function() {
343 343
 	expect(1);
344  
-	ok( /^{ "data"/.test( jQuery.ajax({url: url("data/json_obj.js"), async: false}).responseText ), "check returned text" );
  344
+	ok( /^{ "data"/.test( jQuery.ajax({url: url("data/json_obj.js"), dataType: "text", async: false}).responseText ), "check returned text" );
345 345
 });
346 346
 
347 347
 test("synchronous request with callbacks", function() {
348 348
 	expect(2);
349 349
 	var result;
350  
-	jQuery.ajax({url: url("data/json_obj.js"), async: false, success: function(data) { ok(true, "sucess callback executed"); result = data; } });
  350
+	jQuery.ajax({url: url("data/json_obj.js"), async: false, dataType: "text", success: function(data) { ok(true, "sucess callback executed"); result = data; } });
351 351
 	ok( /^{ "data"/.test( result ), "check returned text" );
352 352
 });
353 353
 
@@ -821,6 +821,25 @@ test("jQuery.ajax() - script, Remote with scheme-less URL", function() {
821 821
 	});
822 822
 });
823 823
 
  824
+test("jQuery.ajax() - malformed JSON", function() {
  825
+	expect(1);
  826
+
  827
+	stop();
  828
+
  829
+	jQuery.ajax({
  830
+		url: "data/badjson.js",
  831
+		dataType: "json",
  832
+		success: function(){
  833
+			ok( false, "Success." );
  834
+			start();
  835
+		},
  836
+		error: function(xhr, msg) {
  837
+			equals( "parsererror", msg, "A parse error occurred." );
  838
+	  		start();
  839
+		}
  840
+	});
  841
+});
  842
+
824 843
 test("jQuery.ajax() - script by content-type", function() {
825 844
 	expect(1);
826 845
 

3 notes on commit 308d6cd

dbj

Ugh, I feel petty , but I had to note that this line in ajax.js (line: 576 ):

     if ( window.JSON && window.JSON.parse ) {

Should probably be :

     if ( window.JSON && ("function" === typeof window.JSON.parse) ) {

Thanks: DBJ

dbj

Ah, I get it now ... For all modern browsers you are simply passing the data string to JSON.parse() without any checks whatsoever.
Leaving it to the implementers of it to throw exception or not if wrong JSON string has arrived.
Your logic is to simply "pass the bucket" to window.JSON ... So if one wants to have her JSON working in all browsers, the same one should sort out her JSON, first. This is OK logic, of course. Not entirely jQuery "hand holding" style, but OK.
In this case you are actually throwing an exception, which I think you should do much more in jQuery in general ;o)

dbj

My attempt is here (at the bottom)
http://dbj.org/dbj/?p=470
I had a luxury of mulling over this while You are in a 1.4 releasing frenzy. Maybe You will find it usefull therefore ...

Thanks: DBJ

Please sign in to comment.
Something went wrong with that request. Please try again.