Tutorial JSON

30 Dic 2010

En un post anterior, comentaba como el formato JSON estaba desbacando al XML en las aplicaciones web: los servicios online más punteros como Foursquare o Twitter están orientando sus APIs hacia este formato convertido en estándar debido a su faclidad de uso, portabilidad y legibilidad.

Actualmente, la cosa va más allá y están empezando a popularizarse lenguajes derivados como el JSONP del que hablaremos en breve. Sin embargo, centremos ahora nuestra atención en JSON y en todo el potencial que encierra para la transmisión de datos vía Internet.

Qué es JSON?

JSON es un acrónimo de JavaScript Object Notation, un formato ligero originalmente concebido para el intercambio de datos en Internet. Se considera un subconjunto de la notación literal para representar objetos, arrays, cadenas, booleanos y números en Javascript.

Su popularización llegó sobre 2001 gracias al apoyo incondicional de Douglas Crockford. Yahoo! ayudó en gran manera a su difusión a raíz de la inclusión de este formato en algunos de sus servicios web más innovadores. En diciembre de 2006, Google comenzaría a ofrecer sus feeds en JSON para su protocolo web GData.

Pese a que JSON se basa en la notación Javascript, está considerado como un lenguaje independiente de formato de datos cuya especificación es descrita en RFC4627.

Anatomía de un objeto JSON

La anatomía de un marcado JSON es casi idéntica a la de un objeto Javascript. Veamos un ejemplo:

{
 "id" : "0001",
 "type" : "donut",
 "name" : "Cake",
 "image" : {
   "url" : "images/0001.jpg",
   "width" : 200,
   "height" : 200
 },
 "thumbnail" : {
   "url" : "images/thumbnails/0001.jpg",
   "width" : 32,
   "height" : 32
 },
 "dateEntry" : "2010-12-05"
}

Como podemos observar, este ejemplo es prácticamente idéntico a la definición de un objeto en Javascript: todo el marcado queda enmarcado entre dos llaves dentro de las cuales, se definen parámetros siguiendo el esquema de pares ‘nombre-valor’. Cada uno de los términos va invariablemente delimitado por comillas, algo que en Javascript no es siempre necesario pero si recomendable.

NOTA: Para comprobar la validez de un marcado JSON existen un par de herramientas online de gran valor: JSONFormatter y JSONLint. En ambos sitios, podemos pegar nuestro código para que sea validado y reformateado.

Particularidades de JSON sobre Javascript

Algunas de las particularidades o reglas del formato JSON a tener en cuenta son:

  • Los pares nombre-valor van siempre delimitados por comillas, independientemente de si se tratan de nombres válidos en Javascript que podrían aparecer sin ellas.
  • JSON puede representar seis tipos de valores: objetos, arrays, numeros, cadenas, booleanos y null.
  • Las fechas no son reconocidas como un tipo de objeto propio.
  • Los numeros en JSON no pueden ir predecidos de ceros salvo en el caso de notación decimal ( Ejm: 0.001 ).

En definitiva, como JSON es considerado un lenguaje independiente, sus objetos deben ser considerados como cadenas Javascript, no como objetos nativos.

Usando JSON en Javascript

El verdadero potencial de JSON es su integración con Javascript. Esto permite un fácil intercambio de datos entre aplicaciones mediante peticiones XHR al servidor a la vez que abre posibilidades ilimitadas a nuevos paradigmas de gestión como los emergentes sistemas No-SQL.

Para permitir que un objeto JSON sea utilizado por Javascript, debemos parsearlo (interpretarlo) mediante el uso del comando eval() tal y como se muestra a continuación:

var myCakes = eval('(' + cakeJSON + ')');
alert(myCakes.name); // donut
alert(myCakes.image.width); // 200

A través de eval(), interpretamos el objeto JSON y lo convertimos en una entidad (objeto) Javascript; esto permite acceder a sus propiedades directamente como con cualquier otro objeto.
Obsérvese que es necesario un doble paréntesis para evitar la ambigüedad con la que Javascript interpreta las llaves con las que comienza el objeto JSON.

NOTA: Para acceder a las propiedades del objeto, utilizamos la notación con punto en lugar de corchetes tal y como recomiendan los expertos:

alert( myCakes[thumbnail][height] ); // Peor
alert( myCakes.thumbnail.height ); // Mejor

Las transacciones XHR, por seguridad, están limitadas únicamente al ámbito del dominio que hace la petición, por lo tanto, cuando se recibe una respuesta, podemos estar 100% seguros de que ésta, proviene del propio dominio. Sin embargo, eso no tiene por que librarnos de un error del servidor o de una redirección maliciosa que nuestro eval() a ciegas puede convertir en desastre.

Siempre es útil recordar ese mantra que inunda foros y artículos y que suele ser lo primero que se graba a fuego en la conciencia de un programador Javascript: eval is evil. Para evitar todos los problemas derivados de una incorrecta interpretación de nuestro código, podemos hacer uso de algunas herramientas de terceros.

Parseando JSON de forma segura

Existen diversas formas que permiten prescindir de eval() delegando la tarea en métodos más seguros.
En jQuery, tenemos por ejemplo el método parseJSON que comprueba la integridad del marcado antes de evaluarlo.
Mootols ofrece también su propio método, JSON.encode(), que realiza una tarea similar al anterior ejemplo de jQuery.

Sin embargo, con la llegada del ECMAScript 5, se ha implementado un nuevo objeto JSON basado en la API programada por el propio Douglas Crockford. Sus métodos más interesantes son parse() y stringify().

JSON.parse ofrece un eval() seguro a través de su filtrado mediante expresiones regulares. Si la cadena no es un objeto JSON válido, devuelve un error de sintaxis y el eval no es llamado.

La sintaxis de este comando es la siguiente:

JSON.parse( string $JSONString [, function $reviver ] );

El primer parámetro recoje la cadena JSON mientras que el segundo, opcional, acepta una función para el tratamiento de dicha cadena. Esta función recoge dos parámetros (clave y valor) y por cada registro del objeto Javascript que estamos componiendo, se evalúan sus pares según el criterio definido. Este método resulta muy práctico para, por ejemplo, convertir las cadenas de fechas en objetos Javascript:

function dateReviver(key, value) {
 if (typeof value === 'string') {
   var a = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
   if (a) {
     return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3]));
   }
 }
 return value;
};
 
var myObj = JSON.parse( myStringJSON, dateReviver);
myObj.dateEntry; //Sat Dec 04 2010 16:00:00 GMT-0800 (Pacific Standard Time)

JSON.stringify hace la operación contraria. Su sintaxis es la siguiente:

JSON.stringify( obj $value [, $replacer] [, @space] );

El primer parámetro $value suele ser un objeto Javascript (o un array) y es a partir del cual, obtenemos la cadena JSON correspondiente.

El segundo parámetro, $replacer, si es una función, actúa básicamente como el $reviver anterior pero de modo inverso. Sin embargo, si le proporcionamos un array, actúa como una lista blanca de aquellas propiedades del objeto que serán serializadas.

El tercer parámetro, $space, puede ser un número o una cadena. En el primer caso, representa el número de espacios en blanco con el que será indentado cada nivel de nuestro JSON. Si usamos una cadena, cada uno de los pares aparecerá indentado con el caracter que hayamos definido. Por lo general, usaremos los caracteres de escape Javascript para indicar tabulaciones o saltos de línea (el más común será ‘\t’ para indicar una tabulación horizontal).

JSON.stringify(myObj, ['id','type','name'], '\t')
/*
'{
   "id" : "0001",
   "type" : "donut",
   "name" : "Cake"
}'
*/

Como podemos ver, el uso de un $replacer resulta interesante para filtrar aquellos pares clave-valor que no nos interesan en un momento dado.

Podemos encontrar ambas funciones en la mayoría de navegadores modernos con la excepción de IE7. Asen Bozhilov ha compilado una tabla comparativa con las diferentes formas en que los fabricantes han implementada JSON.parse.

Más Informacion:

Angus Croll. JSON and JSONP
Douglas Crockford. JSON
Andrés Nieto. Toma de contacto con JSON

Más:

{2} Comentarios.

  1. Rafa

    estoy trabajando con eclipse Birt para hacer reportes y necesito leer un json, este json lo obtengo mediante un servicio rest de la forma http://localhost:8080/reportes/rest/12345.json

    entonces como puedo hacer esto? en su ejemplo usan:
    var myCakes = eval(‘(‘ + cakeJSON + ‘)’);

    deberia poner en vez de cakeJSON la url del servicio rest o como puedo hacerlo?

    • Carlos Benítez

      Hola Rafa;
      si el JSON lo tienes en una URL externa, como es tu caso, necesitas hacer una petición de tipo XHR desde donde quieras trabajar con él (entiendo que otra página web en tu proyecto Birt).

      Necesitas entonces usar algo tipo jQuery.ajax() o la reciente API Fetch (analizada en este mismo blog) para traerte esos datos JSON y comenzar a utilizarlos.

      Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *