JavaScript Object Notation (JSON) is a lightweight data-interchange format. Basically, it is nothing more than a JavaScript hash (see an example in Listing 11-26) used to carry object information. But JSON has two great benefits for Ajax interactions: It is easy to read in JavaScript, and it can reduce the size of a web response.

Listing 11-26 - A Sample JSON Object in JavaScript

var myJsonData = {"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}

If an Ajax action needs to return structured data to the caller page for further JavaScript processing, JSON is a good format for the response. This is very useful if, for instance, one Ajax call is to update several elements in the caller page.

For instance, imagine a caller page that looks like Listing 11-27. It has two elements that may need to be updated. One remote helper could update only one of the elements of the page (either the title or the name), but not both.

Listing 11-27 - Sample Template for Multiple Ajax Updates

<h1 id="title">Basic letter</h1>
<p>Dear <span id="name">name_here</span>,</p>
<p>Your e-mail was received and will be answered shortly.</p>
<p>Sincerely,</p>

To update both, imagine that the Ajax response can be a JSON header containing the following array:

[["title", "My basic letter"], ["name", "Mr Brown"]]

Then the remote call can easily interpret this response and update several fields in a row, with a little help from JavaScript. The code in Listing 11-28 shows what could be added to the template of Listing 11-27 to achieve this effect.

Listing 11-28 - Updating More Than One Element from a Remote Response

<?php echo link_to_remote('Refresh the letter', array(
  'url'      => 'publishing/refresh',
  'complete' => 'updateJSON(request, json)'
)) ?>

<?php echo javascript_tag("
function updateJSON(request, json)
{
  var nbElementsInResponse = json.length;
  for (var i = 0; i < nbElementsInResponse; i++)
  {
     Element.update(json[i][0], json[i][1]);
  }
}
") ?>

The complete callback has access to the json header of the response and can pass it to a third-party function. This custom updateJSON() function iterates over the JSON header and for each member of the array, updates the element named by the first parameter with the content of the second parameter.

Listing 11-29 shows how the publishing/refresh action can return a JSON response.

Listing 11-29 - Sample Action Returning a JSON Header

class publishingActions extends sfActions
{
  public function executeRefresh()
  {
    $output = '[["title", "My basic letter"], ["name", "Mr Brown"]]';
    $this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');

    return sfView::HEADER_ONLY;
  }

The HTTP protocol allows JSON to be stored in a response header. As the response doesn't have any content, the action sends it immediately as a header only. This bypasses the view layer entirely and is as fast as a ->renderText(), but with an even smaller response.

Caution There is a severe limitation to the approach shown in Listing 11-29: the maximum size of HTTP headers. There is no official limitation, but large headers may not be well transferred or interpreted by a browser. This means that if your JSON array is large, the remote action should return a normal response, with the JSON as a JavaScript array.

JSON has become a standard among web applications. Web services often propose responses in JSON rather than XML to allow service integration in the client (mashup), rather than on the server. So if you wonder which format to use for communication between your server and a JavaScript function, JSON is probably your best bet.

Tip Since version 5.2, PHP offers two functions, json_encode() and json_decode(), that allow you to convert an array between the PHP syntax and the JSON syntax, and vice versa (php.net/manual/en/ref.json.php). These facilitate the integration of JSON arrays and Ajax in general.