Getting json on Ajax response callback

18,069

Solution 1

This is the correct syntax for retrieving JSON with Prototype

onSuccess: function(response){
   var json = response.responseText.evalJSON();
}

Solution 2

There is a property of Response: Response.responseJSON which is filled with a JSON objects only if the backend returns Content-Type: application/json, i.e. if you do something like this in your backend code:

$this->output->set_content_type('application/json');
$this->output->set_output(json_encode($answer));
//this is within a Codeigniter controller

in this case Response.responseJSON != undefined which you can check on the receiving end, in your onSuccess(t) handler:

onSuccess:function(t) {
  if (t.responseJSON != undefined) 
  {
    // backend sent some JSON content (maybe with error messages?)
  }
  else 
  {
    // backend sent some text/html, let's say content for my target DIV
  }
}

I am not really answering the question about the second parameter of the handler, but if it does exist, for sure Prototype will only provide it in case of proper content type of the response.

Solution 3

This comes from Prototype official :

Evaluating a JavaScript response Sometimes the application is designed to send JavaScript code as a response. If the content type of the response matches the MIME type of JavaScript then this is true and Prototype will automatically eval() returned code. You don't need to handle the response explicitly if you don't need to.

Alternatively, if the response holds a X-JSON header, its content will be parsed, saved as an object and sent to the callbacks as the second argument:

new Ajax.Request('/some_url', { method:'get', onSuccess: function(transport, json){

  alert(json ? Object.inspect(json) : "no JSON object");

}   

});

Use this functionality when you want to fetch non-trivial data with Ajax but want to avoid the overhead of parsing XML responses. JSON is much faster (and lighter) than XML.

Solution 4

You could also just skip the framework. Here's a cross-browser compatible way to do ajax, used in a comments widget:

//fetches comments from the server
CommentWidget.prototype.getComments = function() {
  var commentURL = this.getCommentsURL + this.obj.type + '/' + this.obj.id; 
  this.asyncRequest('GET', commentURL, null);
}


//initiates an XHR request
CommentWidget.prototype.asyncRequest = function(method, uri, form) {
  var o = createXhrObject()
  if(!o) { return null; } 
  o.open(method, uri, true);
  o.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  var self = this;
  o.onreadystatechange =  function () {self.callback(o)};
  if (form) { 
    o.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    o.send(makePostData(form)); 
  } else {
    o.send(''); 
  }  
}

//after a comment is posted, this rewrites the comments on the page
CommentWidget.prototype.callback = function(o) {                  
  if (o.readyState != 4) { return }
  //turns the JSON string into a JavaScript object.
  var response_obj = eval('(' + o.responseText + ')');
  this.comments = response_obj.comments;
  this.refresh()
}

I open-sourced this code here http://www.trailbehind.com/comment_widget

Share:
18,069
AntonioCS
Author by

AntonioCS

PHP/JS Programmer. Also dabble in Java, C/C++ and c#.

Updated on June 28, 2022

Comments

  • AntonioCS
    AntonioCS almost 2 years

    I am trying to create a little ajax chat system (just for the heck of it) and I am using prototype.js to handle the ajax part.

    One thing I have read in the help is that if you return json data, the callback function will fill that json data in the second parameter.

    So in my php file that gets called I have:

    header('Content-type: application/json');
    
    if (($response = $acs_ajch_sql->postmsg($acs_ajch_msg,$acs_ajch_username,$acs_ajch_channel,$acs_ajch_ts_client)) === true)
        echo json_encode(array('lastid' => $acs_ajch_sql->msgid));
    else
        echo json_encode(array('error' => $response));
    

    On the ajax request I have:

    onSuccess: function (response,json) {
                    alert(response.responseText);
                    alert(json);    
                }
    

    The alert of the response.responseText gives me {"lastid": 8 } but the json gives me null.

    Anyone know how I can make this work?

  • AntonioCS
    AntonioCS about 15 years
    Thanks! But I did read somewhere about that second parameter thing :P
  • umpirsky
    umpirsky over 13 years
    Thanks Jose. Yeah, prototypejs.org/learn/introduction-to-ajax it says that second param is json, crap, wont work for me - onSuccess: function(transport, json){ alert(json ? Object.inspect(json) : "no JSON object"); }