Return JSON array using AJAX and Prototype

by frank on February 13, 2007

Well, Prototype is pretty awesome. So is scriptaculous.

However, I was hunting around and I couldn’t find a decent tutorial on how to return an array of data using prototype’s AJAX functions in JSON notation. There is this one, which was helpful, but it did a lot more than I wanted, and I wanted to use the services_JSON class I used in the ajax dropdown example from an earlier post.

So, here is the…

Basic Tutorial on returning JSON formatted data through an AJAX call using Prototype:

First thing I did was download scriptaculous and get it working . Follow the link above and you should find a download pretty easy as well as some info on how to use it.

With that all sorted out you want to learn about how to make an AJAX call using prototype – prototype is incroporated into scriptaculous in case you were wondering. Well in fact scriptaculous is an add on to prototype but whatever.

So, make some basic calls using the AJAX object. Its probably easiest to start with the Ajax.Updater function, but in order to get this example up and running I found it easier to use Ajax.Request.

Once you have AJAX running and returning some simple sample data back, updating a test div or what have you, we can move on to the JSON notation array.

Returning JSON array for Prototype

The first thing you want to do is include the JSON class and create a new object of that class:

include_once('Services_JSON.php');
//make json object...
$json = new Services_JSON();

Now you can use this cool class to encode all sorts of information into JSON notation – not associative arrays though it seems, but I haven’t finished playing around with that yet [correction]I stand corrected on that assumption as David Mintz has kindly pointed out in the comments below[/correction]. Encoding data is really straightforward…

//create array...
$data = array("New York", "New Yorkshire", "New Jersey");
 
//encode and return json data...
echo $json->encode($data);

There are two methods of returning JSON data. One is in the X-JSON header and the other is just in the plain old body of the page just as you would with any other ordinary AJAX request.

I prefer returning the data in the body of the page because there is a limit to how many bytes you can stuff into the X-JSON header, and problems can arise. Also, it seems that the X_JSON header was not intended for large amounts of data, rather, a way of indicating status of the data of the AJAX request. Which makes sense, adds flexibility and all that.

So, back to it. Adding JSON encoded data to the X_JSON header is like so…

header('X-JSON: ('.$json->encode($data).')');

I used this code to add JSON data to the body of the data returned by the AJAX call…

header('Content-type: application/x-json');
//encode and return json data...
echo $json->encode($data);

Now that the data is being returned in the correct format (check that it is by visiting the page generating the data, without forgetting to add any get variables you need) we can move on to handling the data with the Ajax object.

Using Ajax.Request to process the JSON array:

The Ajax.Request method is pretty comprehensive and easy to use to say the least. There is an excellent example of how to use it which pretty much covers everything. But to complete this tutorial I’ll go over what I did.

I used a callback function for the resonse onComplete (there are a number of other responses explained in the link above).

function keywordOutput(currentURL){
    var url = 'ajax-query.php';
    var pars = 'url='+currentURL;
    var myAjax = new Ajax.Request(url, {method: 'get', parameters: pars, onComplete: getResponse});
}

You can see that the above is going to call getResponse() on completion of the AJAX request. All we need to do now is declare getResponse() so that after onComplete is fired the script knows what to do with the data.

function getResponse(oReq, oJSN) {
    var data = eval(oReq.responseText);
    $('test-div').innerHTML = '';
    //populate the list
    for (var i = 0; i < data.length; i++) {
        $('test-div').innerHTML += data[i]+', ';
    }
}

This basically goes through the data returned by the AJAX call, oReq, and outputs it to a test div. If you have also supplied the X-JSON header with JSON data then that will be available in the oJSN variable. Alternatively this function can be declared as a global reposnder so that any AJAX call that fires a particular status code will call this function – you can find out more about global responders on the prototype site.

Wrap up:

So, thats it. If you have any questions, or if I have left something out feel free to leave a comment. Also, here are some resources I came across while researching this so go nuts…

As usual, big props go out to all the tutorials etc. that I found out there in the websphere. And, not to mention the developers and contirbutors of Prototype and Scriptaculous – glad I finally had opportunity to try these libraries out and expect them to save me a whole lot of time and headaches in the future :)

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Fark
  • Reddit
  • StumbleUpon

Profile:  Frank has been programming for the web using PHP, Javascript and numerous libraries and frameworks for the past 5 years. More articles.

{ 15 comments… read them below or add one }

DavidNo Gravatar February 27, 2007 at 5:21 pm

“Now you can use this cool class to encode all sorts of information into JSON notation – not associative arrays though it seems, but I haven’t finished playing around with that yet.”

I didn’t have any trouble getting Services_JSON to encode this:

array ( ‘someKey’=>”someValue”, ‘number’ => 43, ‘array’ =>array(1,2,array(‘this’=>’that’)));

fabrizioNo Gravatar May 27, 2007 at 10:15 am

What about passing json directly through ajax.updater parameters?
var myAjax = new Ajax.Updater(target,url, {method: ‘post’, requestHeaders: {Accept: ‘application/json’}, onSuccess: function(transport){ var json = transport.responseText.evalJSON(true); }, parameters: {‘id_sender’:”,’dests’:'encode($d);?>’}});

clemensNo Gravatar July 9, 2007 at 8:33 pm

if you happen to have php 5.2.0 or higher you can use the standard json_encode() / json_decode() funcitons that are way faster (coded in c, like 100 – 200 times faster)
if you want to keep it portable in case, then try something like this:

if (!function_exists(‘json_encode’)){
//now its portable to php ver. encode($value);
}
function json_decode($value){
global $json;
return $json->decode($value);
}
}

then just use the standard functions json_encode() / json_decode()

clemensNo Gravatar July 9, 2007 at 8:46 pm

oh, that was cutoff by the comments form – see http://www.pastebin.ca/611218 for the full code…

Mike GiffordNo Gravatar August 10, 2007 at 2:48 am

I just installed the pecl json package.

# yum install php-devel

# pecl install json

I then made sure that there was a json.ini file in the /etc/php.d directory restarted apache and I was set.

Interesting framework.

Mike

RyanNo Gravatar August 14, 2007 at 10:27 pm

Hello! Great article — thanks for the contribution. Would you happen to know the best way to store the JSON response as an array so that I can cache it via client-side?
Thanks!
Ryan

KeithNo Gravatar December 19, 2007 at 5:22 pm

I just want to thank you for posting this! It was exactly the pointers I needed to get started.

StanleyNo Gravatar April 16, 2008 at 2:33 am

muy bueno ,me aydo bastante gracias,

lionheart33806No Gravatar June 26, 2008 at 1:19 pm

The content-type recognized by Prototype is “application/json” not “application/x-json”.

roygerNo Gravatar August 22, 2008 at 6:33 am

You should use prototype’s insert method instead of innerHTML (which is Microsoft specific and not a standart)
http://www.prototypejs.org/api/element/insert

spentNo Gravatar September 10, 2008 at 1:13 pm

Actually lionheart33806, the latest prototype is looking for X-JSON and not JSON.

_getHeaderJSON: function() {
var json = this.getHeader(‘X-JSON’);
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
}

SeanNo Gravatar September 10, 2008 at 2:00 pm

Should it be:

header(‘Content-type: application/json’);

instead of:

header(‘Content-type: application/x-json’);

dietbriskNo Gravatar May 26, 2009 at 6:24 pm

worst written article ever. but the code set me straight.

frankNo Gravatar May 27, 2009 at 11:07 am

@dietbrisk thanks!

BlockBusterNo Gravatar December 5, 2009 at 2:15 am

I didn’t get this :\ can somebody pls explain?

Leave a Comment

{ 1 trackback }

Previous post:

Next post: