38

I have an $.ajax() request with the dataType set to "json." The server is returning JSON with the correct mime type of "application/json." And yet the responseText in my jqXHR object is always a string. What am I doing wrong? Is this how it's supposed to work?

Here's how I'm making the call:

var options = { 
    dataType:'json',
    type: 'GET',
    url: "http://example.com/api/"
};

var key = "PassToCallback";

var jqXHRObject =  $.ajax(options).then(
    function(data, textStatus, jqXHR, key) {
        this.success(data, textStatus, jqXHR, key);
    },
    function(jqXHR, textStatus, errorThrown) { 
        this.error(jqXHR, textStatus, errorThrown);
    }
);

console.log(jqXHRObject.getResponseHeader("content-type")); // application/json
console.log(typeof jqXHRObject.responseText); // string

So I have have to do a $.parseJSON(jqXHRObject.responseText) to get an actual object. This seems unnecessary as $.ajax() should be automatically converting responseText according to the docs. Thanks!

Chandu
  • 81,493
  • 19
  • 133
  • 134

5 Answers5

54

I had the same problem. I returns a string because it formulated from an exception. E.g. I use a kernel listener with serialization to json on my Symfony2 project. Which is correct for proper REST headers.

Anyway, just parse it; this works for me:

$.ajaxSetup({
    "error": function(jqXHR, status, thrownError) {
        alert('error');
        var responseText = jQuery.parseJSON(jqXHR.responseText);
        console.log(responseText);
    }
});
Tjorriemorrie
  • 16,818
  • 20
  • 89
  • 131
  • 30
    This is no longer necessary: http://bugs.jquery.com/ticket/13917#comment:2 "*As of this commit: […] parsed JSON is available in case of failures as the responseJSON field of the jqXHR instance.*" – Asherah Nov 27 '13 at 01:47
25

Try

$.ajaxSetup({
    "error": function(jqXHR, status, thrownError) {
        alert('error');            
        console.log(jqXHR.responseJSON);
    }
});
chridam
  • 100,957
  • 23
  • 236
  • 235
3

You are using $.ajax in a way the docs don't describe. Using json as the dataType just means that the data passed to the success callback will be parsed. Use it like this:

$.ajax({
  dataType:'json',
  type: 'GET',
  url: "http://example.com/api/"
  success: function(data, textStatus, jqXHR) {
    // `data` contains parsed JSON
  },
  error: function(jqXHR, textStatus, errorThrown) {
     // Handle any errors
  }
});
kcbanner
  • 4,050
  • 1
  • 25
  • 18
  • 1
    That's actually what I am doing... I'm just using jQuery's Deferred Objects, documented [here](http://api.jquery.com/category/deferred-object/) which states that $.ajax() will return a deferred object. The .then() calls the success and error callbacks. I'm doing this to take full advantage of jqXHR deferred objects. –  Apr 28 '11 at 23:39
  • Ah, I see! I'm not sure about using those in this case then, sorry. – kcbanner Apr 29 '11 at 13:55
  • 1
    According to the docs for error, "Note: This handler is not called for cross-domain script and JSONP requests." – i_am_jorf Oct 04 '11 at 18:01
  • Correct, but this is a JSON response, not JSONP – kcbanner Oct 04 '11 at 19:17
  • From the jQuery docs: "If json is specified [in the request], the response is parsed using jQuery.parseJSON before being passed, as an object, to the success handler. The parsed JSON object is made available through the responseJSON property of the jqXHR object." – LukeSolar Aug 06 '15 at 22:29
2

I don't see anything in the documentation that suggests responseText would be anything other than exactly what the name implies: text.

Why not just use .getJSON? That would get rid of half of the code you wrote, and it'll convert the response to JSON. Win/win.

michaeltomer
  • 445
  • 3
  • 7
  • [$ajax() documentation](http://api.jquery.com/jQuery.ajax/) under dataTypeString: "'json': Evaluates the response as JSON and returns a JavaScript object." I am not using .getJSON because I use the same method to get multiple types of data (json and html). –  Apr 28 '11 at 23:14
  • *meant under dataType, accidentally copied the String from the next line. Just to clarify. –  Apr 28 '11 at 23:35
-1

Step 1: Stringify the jqXHR

var errorString = JSON.stringify(jqXHR.responseText);

Step 2: change that string to Jquery Object

var $errorObj = $(errorString);

Step 3: Find and get what part of responseText you want.

var errorMessage = $errorObj.find('p').eq(1).text(); 

/* Here Im finding `Message:` thrown by the server, which is inside <p> tag */

Thats it.

$.ajax( /* ... */ ).fail( function(jqXHR, textStatus, errorThrown) {

     var errorString = JSON.stringify(jqXHR.responseText);
     var $errorObj = $(errorString);
     var errorMessage = $errorObj.find('p').eq(1).text();

     alert(errorMessage);

    } );
Aravindh Gopi
  • 2,083
  • 28
  • 36