API do Java para processamento JSON: Introdução a JSON

Por Jitendra Kotamraju
Postado em Julho 2014

A API do Java para processamento JSON fornece APIs portáteis que permitem analisar, gerar, transformar e consultar JSON.
JSON (JavaScript Object Notation) é um formato leve para intercâmbio de dados, baseado em texto e independente da linguagem de programação, fácil de escrever e ler tanto para seres humanos como para máquinas. JSON pode representar dois tipos estruturados: objetos e matrizes. Um objeto é uma coleção não ordenada de zero ou mais pares de nomes/valores. Uma matriz é uma sequência ordenada de zero ou mais valores. Os valores podem ser strings, números, booleanos, nulos e estes dois tipos estruturados.
A Lista 1 é um exemplo tomado da Wikipédia que mostra a representação JSON de um objeto descrevendo uma pessoa. O objeto tem valores string para nome e sobrenome, um valor numérico para a idade, um valor de objeto que representa o endereço da pessoa e um valor 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" 
        }
     ] 
}

Lista 1. Exemplo de representação de um objeto em JSON


JSON é frequentemente utilizado em aplicações Ajax, configurações, bancos de dados e serviços web RESTful. Todos os web sites populares oferecem JSON como formato para intercâmbio de dados com seus serviços web RESTful.


Processamento JSON
A API do Java para processamento JSON (JSR 353) fornece APIs portáteis que permitem analisar, gerar, transformar e consultar JSON usando APIs de modelos de objetos e de streaming.
A API de modelos de objetos cria uma estrutura de árvore, de acesso aleatório, representando os dados JSON armazenados na memória. É possível percorrer a árvore e fazer consultas. Este modelo de programação é o mais flexível e permite processamento em casos que requerem acesso aleatório à totalidade do conteúdo da memória. No entanto, com frequência não é tão eficiente como o modelo de streaming e precisa de mais memória.
A API de streaming oferece um modo de análise e geração de JSON em streams. Oferece controle sobre análise e geração ao programador. A API de streaming fornece um analisador baseado em eventos e permite que um desenvolvedor de aplicações possa requisitar o próximo evento em vez de ter que se ocupar do evento em um retorno de requisição. Assim, o desenvolvedor tem maior controle procedimental do processamento JSON. O código de aplicação pode processar ou descartar o evento do analisador e requisitar o próximo evento (puxar o evento). O modelo de streaming é adequado para o processamento local quando não se requer acesso aleatório a outras porções da informação. De maneira similar, a API de streaming permite gerar JSON bem formado em stream, escrevendo um evento de cada vez.

A API de modelos de objetos
A API de modelos de objetos é semelhante à API de modelos de objetos de documento (DOM) para XML. É uma API de alto nível que fornece modelos de objetos imutáveis para estruturas de objetos e matrizes JSON. Estas estruturas JSON são representadas como modelos de objetos usando os tipos do Java JsonObject e JsonArray. Na Tabela 1 são incluídas as classes e interfaces principais da API de modelos de objetos.
JsonObject oferece uma vista Map para acessar a coleção não ordenada de zero ou mais pares de nomes/valores do modelo. De maneira similar, JsonArray oferece uma vista List para acessar a sequência ordenada de zero ou mais valores do modelo.

Tabela 1. Classes principais da API de modelos de objetos


Classe ou interface

Descrição

Json

Contém métodos estáticos para criar leitores, escritores, construtores de JSON e seus objetos de fábrica.

JsonGenerator

Escreve dados JSON em forma de stream, com um valor de cada vez.

JsonReader

Lê dados JSON de um stream e cria um modelo de objeto na memória.

JsonObjectBuilder
JsonArrayBuilder

Criam um modelo de objeto ou um modelo de matriz na memória, adicionando valores do código de aplicação.

JsonWriter

Escreve um modelo de objeto da memória em um stream.

JsonValue
JsonObject
JsonArray
JsonString
JsonNumber

Representam tipos de dados para valores em dados JSON.

 

JsonObject, JsonArray, JsonString e JsonNumber são subtipos de JsonValue. Há constantes definidas na API para valores JSON nulos, verdadeiros e falsos.
A API de modelos de objetos usa padrões geradores para criar estes modelos de objetos de zero. O código de aplicação pode usar a interface JsonObjectBuilder para criar modelos representando objetos JSON. O modelo obtido é do tipo JsonObject. O código de aplicação pode usar a interface JsonArrayBuilder para criar modelos representando matrizes JSON. O modelo obtido é do tipo JsonArray.
Estes modelos de objetos também podem ser criados a partir de uma origem de entrada (por exemplo, InputStream ou Reader) usando a interface JsonReader. De maneira similar, os modelos de objetos podem ser escritos em uma origem de saída (por exemplo, OutputStream ou Writer) usando a classe JsonWriter.

Por exemplo, vamos escrever código para realizar uma pesquisa em postagens públicas do Facebook usando a API de modelos de objetos. A API do Facebook retorna os resultados da pesquisa no formato JSON, mostrado na Lista 2.
 

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

Lista 2. Representação JSON de uma pesquisa em postagens públicas no Facebook

Podemos usar a API de modelos de objetos para obter nomes e suas postagens públicas relacionadas com o termo java. Na Lista 3, as linhas 1 a 3 criam JsonReader; a linha 5 cria JsonObject com os resultados; a linha 7 volta sobre cada resultado; e as linhas 8 a 11 obtêm o nome da pessoa que postou e a postagem, e imprimem. Note-se que JsonReader e outros objetos desta API podem ser usados na instrução try-with-resources (também chamada de gerenciamento automático 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("-----------");
        }
   }

 Lista 3. Processamento das postagens no Facebook com a API de modelos de objetos



A API de streaming

A API de streaming é semelhante à API de streaming para XML (StAX) e é constituída pelas interfaces JsonParser e JsonGenerator. JsonParser contém métodos para analisar dados JSON usando o modelo de streaming. JsonGenerator contém métodos para escrever dados JSON em uma origem de saída. Na Tabela 2 são incluídas as classes e interfaces principais da API de streaming.

Tabela 2. Classes principais da API de streaming


Classe ou interface

Descrição

Json

Contém métodos estáticos para criar analisadores e geradores JSON, e seus objetos de fábrica.

JsonParser

Representa um analisador baseado em eventos que pode ler dados JSON em um stream.

JsonGenerator

Escreve dados JSON em forma de stream, com um valor de cada vez.

 

JsonParser fornece acesso direto de somente leitura a dados JSON, usando o modelo de programação com análise pull. Neste modelo, o código de aplicação controla o subprocesso e requisita métodos na interface do analisador para fazê-lo avançar ou obter dados JSON do estado atual do analisador.
JsonGenerator fornece métodos para escrever dados JSON em um stream. O gerador pode ser usado para escrever pares de nomes/valores em objetos JSON e valores em matrizes JSON.
A API de streaming é uma API de baixo nível, projetada para processar grandes quantidades de dados JSON de maneira eficiente. Outras estruturas JSON (por exemplo, ligações JSON) podem ser implementadas usando esta API.
A seguir, vamos usar a API de streaming com o mesmo fim que usamos a API de modelos de objetos, isto é, vamos fazer uma pesquisa de postagens públicas no Facebook sobre java. Na Lista 4, as linhas 1 a 3 criam um analisador de streaming; as linhas 4 a 5 obtêm o próximo evento; a linha 6 procura o evento KEY_NAME; as linhas 8 a 11 leem os nomes e imprimem; e as linhas 14 a 16 leem as postagens públicas e imprimem. O uso da API de streaming é um modo eficiente de acessar nomes e suas postagens públicas se comparado com o uso da API de modelos de objetos para realizar o mesmo trabalho.

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;
               }
           }
       }
   }

Lista 4. Processamento das postagens no Facebook com a API de streaming

Conclusão
A API do Java para processamento JSON oferece as seguintes capacidades:

  • Analisa streams de entrada em objetos imutáveis ou streams de eventos
  • Escreve streams de eventos ou objetos imutáveis como streams de saída
  • Navega mediante programação objetos imutáveis
  • Constrói de maneira programada objetos imutáveis com geradores

A API serve como base para o desenvolvimento de APIs de transformação, pesquisa, ligação ou outras manipulações de dados. JAX-RS 2.0 oferece integração nativa para a API do Java para processamento JSON.
Informações adicionais



Jitendra Kotamraju, integrante principal da equipe técnica da Oracle, dirige o projeto de especificação do processamento JSON e é um dos engenheiros mais importantes em relação com GlassFish. Antes de dirigir o projeto JSON, foi responsável pela especificação e implementação de JAX-WS 2.2.