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
A API do Java para processamento JSON oferece as seguintes capacidades:
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.
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.