API de Java para procesamiento JSON: Introducción a JSON

Por Jitendra Kotamraju
Publicado en Julio 2014

La API de Java para procesamiento JSON proporciona rutinas API portátiles que permiten analizar, generar, transformar y consultar JSON.

JSON (JavaScript Object Notation) es un formato para intercambio de datos liviano, basado en texto e independiente del lenguaje de programación, que resulta fácil de escribir y leer tanto para los seres humanos como para las máquinas. JSON puede representar dos tipos estructurados: objetos y matrices. Un objeto es una colección no ordenada de cero o más pares de nombres/valores. Una matriz es una secuencia ordenada de cero o más valores. Los valores pueden ser cadenas, números, booleanos, nulos y estos dos tipos estructurados.

El Listado 1 constituye un ejemplo tomado de Wikipedia que muestra la representación JSON de un objeto que describe a una persona. El objeto tiene valores de cadena para nombre y apellido, un valor numérico para la edad, un valor de objeto que representa el domicilio de la persona y un valor de matriz de objetos de números telefónicos.

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": {
        "streetAddress": "21 2nd  Street",
        "city": "New York",
        "state": "NY",
        "postalCode": 10021
     },
     "phoneNumbers": [
        {
            "type": "home",
            "number": "212  555-1234"
        },
        {
            "type": "fax",
            "number": "646  555-4567" 
        }
     ] 
}

Listado 1. Ejemplo de representación de un objeto en JSON

JSON suele utilizarse en aplicaciones Ajax, configuraciones, bases de datos y servicios web RESTful. Todos los sitios web populares ofrecen JSON como formato para intercambio de datos con sus servicios web RESTful.

Procesamiento JSON

La API de Java para procesamiento JSON (JSR 353) proporciona rutinas API portátiles que permiten analizar, generar, transformar y consultar JSON usando rutinas API de modelos de objetos y de streaming.

La API de modelos de objetos crea una estructura de árbol, de acceso aleatorio, que representa los datos JSON almacenados en la memoria. Es posible recorrer el árbol y formular consultas. Este modelo de programación es el más flexible y posibilita el procesamiento en casos en que se requiera acceso aleatorio a la totalidad del contenido de la memoria. Sin embargo, a menudo no es tan eficiente como el modelo de streaming y requiere más memoria.

La API de streaming ofrece un modo de analizar y generar JSON en streams. Le otorga al programador el control sobre el análisis y la generación. La API de streaming ofrece un analizador basado en eventos y brinda al desarrollador de aplicaciones la posibilidad de "pedir" el evento siguiente en lugar de tener que ocuparse del evento en una devolución de llamada. De este modo, el desarrollador cuenta con mayor control procedimental del procesamiento JSON. El código de aplicación puede procesar o descartar el evento del analizador y pedir el siguiente evento (extraer el evento). El modelo de streaming es adecuado para el procesamiento local cuando no se requiere acceso aleatorio a otras porciones de la información. De manera similar, la API de streaming permite generar JSON bien formado en stream escribiendo un evento por vez.

La API de modelos de objetos

La API de modelos de objetos es similar a la API de modelos de objetos de documento (DOM) para XML. Es una API de alto nivel que proporciona modelos de objetos inmutables para estructuras de objetos y matrices JSON. Estas estructuras JSON se representan como modelos de objetos usando los tipos de Java JsonObject y JsonArray. En la Tabla 1 se incluyen las clases e interfaces principales de la API de modelos de objetos. JsonObject suministra una vista Map para obtener acceso a la colección no ordenada de cero o más pares de nombres/valores del modelo. De modo similar, JsonArray ofrece una vista List para obtener acceso a la secuencia ordenada de cero o más valores del modelo.

Tabla 1. Clases principales de la API de modelos de objetos

Clase o interfaz >Descripción
Json Contiene métodos estáticos para crear lectores, escritores, constructores de JSON y sus objetos de fábrica.
JsonGenerator Escribe datos JSON en forma de stream, con un valor por vez.
JsonReader Lee datos JSON de un stream y crea un modelo de objeto en la memoria.
JsonObjectBuilder

JsonArrayBuilder
Crean un modelo de objeto o un modelo de matriz en la memoria agregando valores del código de aplicación.
JsonWriter Escribe un modelo de objeto de la memoria en un stream.
JsonValue

JsonObject

JsonArray

JsonString

JsonNumber

Representan tipos de datos para valores en datos JSON.

JsonObject, JsonArray, JsonString y JsonNumber son subtipos de JsonValue. Hay constantes definidas en la API para valores JSON nulos, verdaderos y falsos.

La API de modelos de objetos usa patrones generadores para crear estos modelos de objetos desde cero. El código de aplicación puede usar la interfaz JsonObjectBuilder para crear modelos que representen objetos JSON. El modelo que se obtiene es del tipo JsonObject. El código de aplicación puede usar la interfaz JsonArrayBuilder para crear modelos que representen matrices JSON. El modelo que se obtiene es del tipo JsonArray.

Estos modelos de objetos también pueden crearse a partir de un origen de entrada (por ejemplo InputStream o Reader) usando la interfaz JsonReader. De modo similar, los modelos de objetos pueden escribirse en un origen de salida (por ejemplo OutputStream o Writer) usando la clase JsonWriter.

Por ejemplo, escribamos código para efectuar una búsqueda en los posts públicos de Facebook usando la API de modelos de objetos. La API de Facebook devuelve los resultados de la búsqueda en el formato JSON que se muestra en el Listado 2.

{
        "data" : [
           { "from" : {  "name" : "xxx", ... }, "message" :  "yyy", ... },
           { "from" : {  "name" : "ppp", ... }, "message" :  "qqq", ... },
           ...
        ],
        ...
}

Listado 2. Representación JSON de una búsqueda en los posts públicos de Facebook

Podemos usar la API de modelos de objetos para obtener nombres y sus posts públicos relacionados con el término java. En el Listado 3, las líneas 1 a 3 crean JsonReader; la línea 5 crea JsonObject para los resultados; la línea 7 itera respecto de cada resultado; y las líneas 8 a 11 obtienen el nombre de la persona que publicó el post y el post en sí, y los imprimen. Nótese que JsonReader y otros objetos de esta API pueden usarse en la instrucción try-with-resources (que también se denomina gestión automática de recursos [ARM]).

URL url = new  URL("https://graph.facebook.com/search?q=java&type=post");
   try (InputStream is = url.openStream();
        JsonReader rdr = Json.createReader(is)) {
        JsonObject obj = rdr.readObject();
        JsonArray results = obj.getJsonArray("data");
        for (JsonObject result : results.getValuesAs(JsonObject.class)) {
            System.out.print(result.getJsonObject("from").getString("name"));
            System.out.print(": ");
            System.out.println(result.getString("message", ""));
            System.out.println("-----------");
        }
   }

Listado 3. Procesamiento de posts de Facebook con la API de modelos de objetos

La API de streaming

La API de streaming es similar a la API de streaming para XML (StAX) y está constituida por las interfaces JsonParser y JsonGenerator. JsonParser contiene métodos para analizar datos JSON usando el modelo de streaming. JsonGenerator contiene métodos para escribir datos JSON en un origen de salida. En la Tabla 2 se incluyen las clases e interfaces principales de la API de streaming.

Tabla 2. Clases principales de la API de streaming 

Clase o interfaz Descripción
Json Contiene métodos estáticos para crear analizadores y generadores JSON, y sus objetos de fábrica.
JsonParser Representa un analizador basado en eventos que puede leer datos JSON en un stream.
JsonGenerator Escribe datos JSON en forma de stream, con un valor por vez.

JsonParser proporciona acceso directo de solo lectura a datos JSON usando el modelo de programación con análisis pull. En este modelo, el código de aplicación controla el subproceso y llama métodos en la interfaz del analizador para hacer avanzar el analizador u obtener datos JSON del estado actual del analizador.

JsonGenerator proporciona métodos para escribir datos JSON en un stream. El generador puede usarse para escribir pares de nombres/valores en objetos JSON y valores en matrices JSON. La API de streaming es una API de bajo nivel diseñada para procesar grandes cantidades de datos JSON de manera eficiente. Con esta API, es posible implementar otros marcos JSON (por ejemplo, enlaces JSON).

A continuación, utilizaremos la API de streaming con el mismo fin que usamos la API de modelos de objetos, es decir, llevar a cabo una búsqueda de posts públicos de Facebook sobre java. En el Listado 4, las líneas 1 a 3 crean un analizador de streaming; las líneas 4 a 5 obtienen el evento siguiente; la línea 6 busca el evento KEY_NAME; las líneas 8 a 11 leen los nombres y los imprimen; y las líneas 14 a 16 leen los posts públicos y los imprimen. El uso de la API de streaming proporciona un modo eficiente de obtener acceso a nombres y sus posts públicos si se compara con el uso de la API de modelos de objetos para llevar a cabo la misma tarea.

URL url = new  URL("https://graph.facebook.com/search?q=java&type=post");
   try (InputStream is = url.openStream();
         JsonParser parser = Json.createParser(is)) {
        while (parser.hasNext()) {
            Event e = parser.next();
            if (e == Event.KEY_NAME) {
                switch (parser.getString()) {
                   case "name":
                        parser.next();
                       System.out.print(parser.getString());
                      System.out.print(":  ");
                      break;
                  case "message":
                      parser.next();
                      System.out.println(parser.getString());
                      System.out.println("---------");
                      break;
               }
           }
       }
   }

Listado 4. Procesamiento de posts de Facebook con la API de streaming

Conclusión

La API de Java para procesamiento JSON proporciona las capacidades siguientes:

  • Analiza streams de entrada en objetos inmutables o streams de eventos
  • Escribe streams de eventos u objetos inmutables como streams de salida
  • Navega mediante programación objetos inmutables
  • Construye mediante programación objetos inmutables con generadores

La API sirve como base para desarrollar rutinas API de transformación, consulta, enlace u otras manipulaciones de datos. JAX-RS 2.0 suministra integración nativa para la API de Java para procesamiento JSON. Información adicional

Jitendra Kotamraju, integrante principal del equipo técnico de Oracle, dirige el proyecto de especificación del procesamiento JSON y es uno de los ingenieros más importantes en relación con GlassFish. Antes de dirigir el proyecto de procesamiento JSON, estuvo a cargo de la especificación e implementación de JAX-WS 2.2.