JSON (JavaScript Object Notation) es un formato sencillo para intercambiar datos. Consiste básicamente en un array asociativo de JavaScript (ver ejemplo en el listado 11-26) que se utilizar para incluir información del objeto. JSON ofrece 2 grandes ventajas para las interacciones Ajax: es muy fácil de leer en JavaScript y puede reducir el tamaño en bytes de la respuesta del servidor.

Listado 11-26 - Ejemplo de objeto JSON en JavaScript

var misDatosJson = {"menu": {
  "id": "archivo",
  "valor": "Archivo",
  "popup": {
    "menuitem": [
      {"value": "Nuevo", "onclick": "CrearNuevoDocumento()"},
      {"value": "Abrir", "onclick": "AbrirDocumento()"},
      {"value": "Cerrar", "onclick": "CerrarDocumento()"}
    ]
  }
}}

El formato JSON es el más adecuado para la respuesta del servidor cuando la acción Ajax debe devolver una estructura de datos a la página que realizó la llamada de forma que se pueda procesar con JavaScript. Este mecanismo es útil por ejemplo cuando una sola petición Ajax debe actualizar varios elementos en la página.

En el listado 11-27 se muestra un ejemplo de página que contiene 2 elementos que deben ser actualizados. Un helper remoto solo puede actualizar uno de los elementos de la página (o titulo o nombre) pero no los 2 a la vez.

Listado 11-27 - Plantilla de ejemplo para actualizaciones Ajax múltiples

<h1 id="titulo">Carta normal</h1>
<p>Estimado <span id="nombre">el_nombre</span>,</p>
<p>Hemos recibido su email y le contestaremos en el menor plazo de tiempo.</p>
<p>Reciba un saludo cordial,</p>

Para actualizar los 2 elementos, la respuesta Ajax podría consistir en una única cabecera JSON cuyo contenido fuera el siguiente array:

[["titulo", "Mi carta normal"], ["nombre", "Sr. Pérez"]]

Mediante algunas pocas instrucciones de JavaScript se puede interpretar la respuesta del servidor y actualizar varios elementos de la página de forma seguida. El listado 11-28 muestra el código que se podría añadir a la plantilla del listado 11-27 para conseguir este efecto.

Listado 11-28 - Actualizando más de un elemento mediante una respuesta remota

<?php echo link_to_remote('Actualizar la carta', array(
  'url'      => 'publicaciones/actualizar',
  'complete' => 'actualizaJSON(request, json)'
)) ?>

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

El callback complete tiene acceso directo a la cabecera json de la respuesta y por tanto puede enviarlo a una función externa. La función actualizaJSON() recorre la cabecera JSON y para cada elemento del array actualiza el elemento cuyo atributo id coincide con el primer parámetro del array y muestra el contenido incluido en el segundo parámetro del array.

El listado 11-29 muestra como devuelve la acción publicaciones/actualizar una respuesta de tipo JSON.

Listado 11-29 - Ejemplo de acción que devuelve una cabecera JSON

class publicacionesActions extends sfActions
{
  public function executeActualizar()
  {
    $resultado = '[["titulo", "Mi carta normal"], ["nombre", "Sr. Pérez"]]';
    $this->getResponse()->setHttpHeader("X-JSON", '('.$resultado.')');

    return sfView::HEADER_ONLY;
  }

El protocolo HTTP permite que la respuesta JSON se pueda enviar como una cabecera de la respuesta. Como la respuesta no tiene ningún contenido, la acción envía solo la cabecera de forma inmediata. De esta forma, se evita completamente la capa de la vista y es tan rápido como ->renderText() pero además con una respuesta más pequeña.

Advertencia Existe una limitación muy importante a la técnica mostrada en el listado 11-29: el tamaño máximo de las cabeceras HTTP. Aunque no existe un límite oficial, las cabeceras grandes pueden no transmitirse correctamente o no interpretarse bien en el navegador. De esta forma, si el array JSON es grande, la acción remota debería devolver una respuesta normal con los datos JSON incluídos como un array de JavaScript.

JSON se ha convertido en un estandar en el desarrollo de aplicaciones web. Los servicios web proponen la utilización de JSON en vez de XML para permitir la integración de servicios en el navegador del usuario en vez de en el servidor. El formato JSON es seguramente la mejor opción para el intercambio de información entre el servidor y las funciones JavaScript.

Truco Desde la versión 5.2 de PHP existen 2 funciones, json_encode() y json_decode(), que permiten convertir un array PHP en un array JSON y viceversa (http://www.php.net/manual/es/ref.json.php). Estas funciones facilitan la integración de los arrays JSON y de Ajax en general.