3

Google returns Unparsable Cuft to the json response like this:

throw 1; <dont be evil> { foo: bar}
  • My current web applications use jQuery.Ajax to retrieve JSON data. How should they be modified to consume valid data?

Here is a relevant demo

Community
  • 1
  • 1
makerofthings7
  • 60,103
  • 53
  • 215
  • 448

2 Answers2

5

You should probably remove the beginning part from the response:

$.ajax(url, {
    dataType: "jsonp text",
    success: function(data) {
        var jsonString = data.replace(/^throw 1; <dont be evil> /, "");
        var responseObject = $.parseJSON(jsonString);

        // do something with responseObject
        ...
    }
}


UPDATE:

To make the re-writing available in every Ajax call you could also register a global Ajax Converter in jQuery:

$.ajaxSetup({
    converters: {
        "text cleanedjson": function(data) {
            var jsonString = data.replace(/^throw 1; <dont be evil> /, "");
            return $.parseJSON(jsonString);
        }
    }
});

$.ajax(url, {
    dataType: "jsonp cleanedjson",
    success: function(responseObject) {
        // do something with responseObject
        ...
    }
});

You will still need to specify your defined dataType in the request options.


UPDATE 2: If you need to tweak your existing calls to do the response cleanup automatically, you could patch jQuery's ajax implementation to automatically use your converter in certain situations:

// store reference to original implementation
$._ajax_original = $.ajax;

// redefine jQuery's ajax function
$.ajax = function(url, settings) {
    if (… your test for applicability here (e.g. an url check) …) {
        settings.dataType = "jsonp cleanedjson";
    }
    return $._ajax_original(url, settings);
};

​ Note that this redefinition has to included after loading jQuery and before the first Ajax call is made. You may also need to consider that $.ajax can also be called without a separate url parameter...

Julian D.
  • 5,464
  • 1
  • 25
  • 35
  • `data.substring("throw1; ".length)` is actually way faster, at least on V8. – Linus Thiel Feb 18 '12 at 13:35
  • 2
    Definitely an alternative, but "way faster", for a single replacement? Most likely absolutely irrelevant... – Julian D. Feb 18 '12 at 13:41
  • I'm using Telerik controls and editing the `$.ajax` command means I have to edit the source code and recompile. I was thinking I could leave things as-is, and use prototype to redefine the "global ajax command" and allow all my compiled JSON to go unmodified. Thoughts? – makerofthings7 Feb 18 '12 at 14:51
  • Thanks for the update. This is my first time redefining anything on jQuery. Rather than define my own converter, can I redefine the "base/root" definition for JSON AJAX responses. My goal is to avoid editing the source code and recompiling. I believe this is required with the DataType setting you mention. – makerofthings7 Feb 18 '12 at 22:11
  • I have added a part about patching jQuery's `ajax` function. I would definitely not recommend tweaking the underlying XHR objects: handling the different implementations for all browsers would be quite some work... – Julian D. Feb 19 '12 at 22:47
2

I achieved this a little simpler taking advantage of the $.ajaxSetup method:

http://api.jquery.com/jQuery.ajaxSetup/

and using converters:

$.ajaxSetup({
    converters: {
        "text json": function (stringData) {
            return jQuery.parseJSON(stringData.replace("for(;;);", ""));
        }
    }
});

What this does is tap into every ajax call and makes the necessary conversion/replacement on the fly. It essentially takes your object which it reads as "text", replaces the unparseable cruft, and spits out a new json object.

Works great. I set it and forget it and it won't interfere with any non-tainted json.

Jason
  • 7,612
  • 14
  • 77
  • 127