JSON é um formato de intercâmbio de dados baseado na representação literal de objetos, matrizes (arrays), cadeias de caracteres (string), números (number) e booleanos (boolean) do JavaScript. Seu formato foi originalmente especificado e popularizado por Douglas Crockford, e descrito na RFC 4627.
Com uma estrutura de sintaxe mais simples do que uma estrutura XML, JSON pode ser considerado uma vantagem sobre o XML como protocolo de dados para serviços HTTP/WEB, pois JSON necessita menos consumo de banda para transferir dados em relação ao XML.
JSON é construído em duas estruturas:
Listagem 1. Uma coleção de pares nome/valor.
{
"aluno":
{
"nome":"Aluno X",
"estado":"SP"
}
}
Listagem 2. Uma lista ordenada de valores.
{
"alunos":
[
{
"aluno":
{
"nome":"Aluno X",
"estado":"SP"
}
},
{
"aluno":
{
"nome":"Aluno Y",
"estado":"RJ"
}
}
]
}
O propósito da biblioteca JSON4J (JSON for Java) é facilitar a manipulação de estruturas JSON em ambientes Java e Java Enterprise Edition (Java EE).
Onde obter a biblioteca
O WebSphere Application Server Feature Pack for Web 2.0 oferece um conjunto abrangente de aplicativos e bibliotecas JavaScript que permitem o desenvolvimento de aplicações Java Enterprise Edition (Java EE) com interfaces ricas baseadas na Web 2.0. Dentre estas bibliotecas oferecidas, existe uma chamada JSON4J, que possibilita a construção e manipulação de JavaScript Object Notation (JSON) em ambientes Java e Java Enterprise Edition (Java EE).
A biblioteca JSON4J é incluída no seguinte diretório do WebSphere® Application Server Feature Pack for Web 2.0:
Biblioteca – <raiz_do_servidor_de_apl>/web2fep/optionalLibraries/JSON4J/JSON4J.jar
Documentação – <raiz_do_servidor_de_apl>/web2fep/documentation/JSON4J/index.html
Pré-requisitos
Para que a biblioteca JSON4J funcione adequadamente, é necessário ter Java Technology Edition versão 1.4.2, 5.0 ou 6.0.
Instalação
A instalação da biblioteca JSON4J depende de como o aplicativo será empacotado e como o mesmo funcionará. Dentre as opções de instalação, podemos:
- Incluir a biblioteca no diretório WEB-INF/lib da aplicação;
- Disponibilizar a biblioteca em uma biblioteca compartilhada (shared library);
- Configurar a biblioteca no caminho de classe (classpath) da aplicação.
Limitações
A biblioteca JSON4J segue a definição do formato JSON, e é mais rígida do que a maioria dos navegadores web no que tange a sintaxe de uma estrutura JSON. JSON4J, por exemplo, não considera como uma estrutura JSON válida nomes de atributos que não estejam entre aspas. Nestes casos a biblioteca irá lançar uma exceção do tipo java.io.IOException. Portanto, sempre mantenha nomes de atributos entre aspas para uma correta análise da biblioteca.
Listagem 3. Exemplo de uma estrutura válida.
{
"nomeDoAtributo": "teste"
}
Listagem 4. Exemplo de uma estrutura inválida.
{
nomeDoAtributo: teste
}
Utilizando a biblioteca JSON4J
Vamos criar alguns exemplos de aplicações Java (WEB) para demonstrar o funcionamento da biblioteca JSON4J. Não será foco nos exemplos a aplicação de boas práticas de programação, pois o intuito é apresentar o funcionamento da biblioteca JSON4J.
Para a elaboração dos exemplos utilizamos o IBM Rational Software Architect for WebSphere, com a versão do Java 1.6 (IBM J9 VM) em um ambiente Java EE 5.0.
Em alguns exemplos utilizaremos o Value Object da listagem 5.
Listagem 5. Value Object – AlunoVo.
public class AlunoVo implements Serializable {
private String nome;
private String sexo;
private Long idade;
private String estado;
private Double nota;
private Boolean ativo;
//Implementação omitida dos métodos getters e setters.
}
Exemplo 1 – Construindo uma estrutura JSON a partir de um Value Object
A listagem 6 mostra o código de um Servlet que executa um método chamado “buscarAlunoDeAlgumLugar”. Este método busca informações de um aluno (que podem ser reunidas de um banco de dados relacional, mainframe, etc.) e cria um objeto do tipo “AlunoVo” (estrutura apresentada na listagem 5).
Após isso, construímos um objeto do tipo com.ibm.json.java.JSONObject. Na referência criada, utilizamos o método “put” para incluirmos uma chave (que representa o nome do atributo da estrutura JSON) e um valor (que representa o valor do atributo criado). Realizamos esta tarefa para cada atributo que desejamos incluir na estrutura JSON.
Para obter a estrutura JSON, basta chamar o método “serialize” da classe com.ibm.json.java.JSONObject. Este método retorna uma referência de objeto do tipo java.lang.String contendo toda a estrutura JSON criada. Este processo também é conhecido por serialização.
Pronto! De uma maneira simples já obtemos a nossa estrutura JSON a partir de um Value Object (VO).
Listagem 6. Código do Servlet – JSON a partir de um Value Object.
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//Buscamos os dados de um aluno.
AlunoVo alunoVo = buscarAlunoDeAlgumLugar();
JSONObject jsonObject = new JSONObject();
//Inserimos os atributos que estarão na nossa estrutura JSON.
jsonObject.put("nome", alunoVo.getNome());
jsonObject.put("sexo", alunoVo.getSexo());
jsonObject.put("idade", alunoVo.getIdade());
jsonObject.put("estado", alunoVo.getEstado());
jsonObject.put("nota", alunoVo.getNota());
//Invocamos o método para serializar para JSON.
String alunoJson = jsonObject.serialize();
response.setContentType("application/json");
response.getOutputStream().print( alunoJson );
response.getOutputStream().flush();
}
Figura 1. Resultado da execução do Servlet em um navegador WEB.
Note que o resultado apresentado na figura 1 está formatado de acordo com os recursos possíveis do navegador WEB (browser). Cada navegador pode tratar de uma maneira particular a apresentação de uma saída application/json.
A classe JSONObject não só funciona como uma mapa, como também estende a classe java.util.HashMap, apesar disso, não é possível inserir em seu valor qualquer objeto que estenda a classe java.lang.Object. Os tipos que podem ser inseridos em um JSONObject são:
Tabela 1. Tipos permitidos em um JSONObject.
null |
java.lang.String |
java.lang.Boolean |
java.lang.Number |
com.ibm.json.java.JSONArray |
com.ibm.json.java.JSONObject |
Caso seja feita uma tentativa de inserir um tipo no valor do mapa diferente dos apresentados acima, será lançada uma exceção do tipo java.lang.IllegalArgumentException.
Exemplo 2 – Construindo uma estrutura JSON a partir de um ArrayList
No exemplo apresentado na listagem 7, vamos fazer uma pequena alteração em nosso código, onde ao invés de retornar apenas um único objeto do tipo “AlunoVo”, retornaremos uma lista de “AlunoVo” (através do método “buscarAlunosDeAlgumLugar”) em um objeto do tipo java.util.ArrayList. Em seguida, percorreremos a lista “alunos”, criaremos um objeto do tipo JSONObject com as propriedades do objeto “alunoVo” e finalmente adicionaremos em um objeto do tipo com.ibm.json.java.JSONArray.
Listagem 7. Código Servlet – JSON a partir de um ArrayList.
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//Buscamos a nossa lista de AlunoVo.
ArrayList<AlunoVo> alunos = buscarAlunosDeAlgumLugar();
JSONObject jsonObject = null;
JSONArray jsonArray = new JSONArray();
//Percorrendo a nossa lista de alunos.
for(AlunoVo alunoVo : alunos) {
//Para cada aluno criamos um JSONObject.
jsonObject = new JSONObject();
jsonObject.put("nome", alunoVo.getNome());
jsonObject.put("sexo", alunoVo.getSexo());
jsonObject.put("idade", alunoVo.getIdade());
jsonObject.put("estado", alunoVo.getEstado());
jsonObject.put("nota", alunoVo.getNota());
//Adicionamos cada JSONObject criado em nosso JSONArray.
jsonArray.add(jsonObject);
}
//Invocamos o método para serializar para JSON.
String alunosJson = jsonArray.serialize();
response.setContentType("application/json");
response.getOutputStream().print( alunosJson );
response.getOutputStream().flush();
}
A classe JSONArray estende a classe java.util.ArrayList e têm as mesmas regras que a classe JSONObject, no que tange aos tipos permitidos para adição (vide Tabela 1).
Figura 2. Resultado da execução do Servlet em um navegador WEB.
Exemplo 3 – Construindo uma estrutura JSON a partir de um XML
No exemplo apresentado na listagem 9, nosso código irá retornar uma cadeia de caracteres no padrão XML e converteremos diretamente o XML retornado pelo método “buscarAlunoDeAlgumLugarXML” para o formato JSON. Para isso vamos utilizar o método estático “transform” da classe com.ibm.json.xml.XMLToJSONTransformer. Um dos seus métodos sobrecarregados recebe um objeto do tipo java.io.InputStream.
Listagem 8. XML que será convertido.
<aluno>
<nome>Aluno W</nome>
<sexo>M</sexo>
<idade>14</idade>
<nota>6.5</nota>
<estado>SP</estado>
<ativo>false</ativo>
</aluno>
Listagem 9. Código Servlet – JSON a partir de um XML.
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//Este método retorna o XML da listagem 8.
InputStream aluno = buscarAlunoDeAlgumLugarXML();
String alunoJson = "";
try {
//Chamada de método para a conversão de XML para JSON.
alunoJson = XMLToJSONTransformer.transform(aluno);
}
catch (SAXException e) {
//Devemos tratar SAXException.
e.printStackTrace();
}
response.setContentType("application/json");
response.getOutputStream().print( alunoJson );
response.getOutputStream().flush();
}
Figura 3. Resultado da execução do Servlet em um navegador WEB.
Exemplo 4 – Construindo uma estrutura JSON complexa a partir de um Value Object
Muitas vezes temos que lidar com estruturas (JSON) mais complexas, onde necessitamos construir uma estrutura com objetos encadeamos. A seguir demonstraremos como a biblioteca JSON4J pode nos ajudar nestas situações.
Especificamente para este exemplo, vamos acrescentar um novo atributo na nossa classe “AlunoVo” que será do tipo “EnderecoVo”. As respectivas classes são apresentadas nas listagens 10 e 11.
Listagem 10. Value Object com novo atributo para este exemplo – AlunoVo.
public class AlunoVo implements Serializable {
private String nome;
private String sexo;
private Long idade;
private String estado;
private Double nota;
private Boolean ativo;
//Novo atributo adicionado.
private EnderecoVo endereco;
//Implementação omitida dos métodos getters e setters.
}
Listagem 11. Value Object – EnderecoVo.
public class EnderecoVo implements Serializable {
private String logradouro;
private Integer numero;
private String complemento;
//Implementação omitida dos métodos getters e setters.
}
No exemplo da listagem 12 executaremos nosso conhecido método “buscarAlunoDeAlgumLugar”. O objeto “AlunoVo” retornado por este método terá adicionalmente os dados de endereço do aluno (“EnderecoVo”). Vale destacar neste exemplo, a criação de um objeto do tipo JSONObject específico para os dados de endereço do aluno, após a isso inserimos o JSONObject com os dados de endereço (do aluno), no JSONObject que representa o aluno. Como já apresentado na tabela 1, um JSONObject permite a inserção de um outro JSONObject.
O resultado da execução do código da listagem 12 pode ser visto na figura 4.
Listagem 12. Código Servlet – Construindo JSON complexo a partir de um Value Object.
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//Buscamos os dados de um aluno.
AlunoVo alunoVo = buscarAlunoDeAlgumLugar();
JSONObject jsonObjectAluno = new JSONObject();
JSONObject jsonObjectEndereco = new JSONObject();
//Inserimos os atributos que estarão na nossa estrutura JSON.
jsonObjectAluno.put("nome", alunoVo.getNome());
jsonObjectAluno.put("sexo", alunoVo.getSexo());
jsonObjectAluno.put("idade", alunoVo.getIdade());
jsonObjectAluno.put("estado", alunoVo.getEstado());
jsonObjectAluno.put("nota", alunoVo.getNota());
//Obtemos o endereço do aluno.
EnderecoVo endereco = alunoVo.getEndereco();
//JSONObject com os dados de endereço.
jsonObjectEndereco.put("logradouro", endereco.getLogradouro());
jsonObjectEndereco.put("numero", endereco.getNumero());
jsonObjectEndereco.put("complemento", endereco.getComplemento());
//Como apresentado na Tabela 1, um JSONObject pode ser inserido em um JSONObject.
jsonObjectAluno.put("endereco", jsonObjectEndereco);
//Invocamos o método para serializar para JSON.
String alunoJson = jsonObjectAluno.serialize();
response.setContentType("application/json");
response.getOutputStream().print( alunoJson );
response.getOutputStream().flush();
}
Figura 4. Resultado da execução do Servlet em um navegador WEB.
Exemplo 5 – Construindo um Value Object a partir de uma estrutura JSON
No exemplo da listagem 14, executaremos um método chamado “buscarAlunoDeAlgumLugarJSON”, este método retorna uma estrutura JSON em uma referência do tipo java.lang.String. O método estático “parse” da classe JSONObject, retornará uma referência do tipo JSONObject, onde assim poderemos resgatar através do método “get” cada atributo da estrutura JSON.
Listagem 13. Estrutura JSON que será convertida em Value Object.
{
"nome":"Aluno Y",
"estado":"SP",
"sexo":"F",
"idade":18,
"nota":9.5,
"ativo":true
}
Listagem 14. Código Servlet – Value Object a partir de uma estrutura JSON.
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//Este método retorna uma estrutura JSON da listagem 13.
String aluno = buscarAlunoDeAlgumLugarJSON();
AlunoVo alunoVo = new AlunoVo();
//Realizamos o parse do JSON obtido.
JSONObject jsonObject = JSONObject.parse(aluno);
//Populamos nosso Value Object.
alunoVo.setNome( (String) jsonObject.get("nome") );
alunoVo.setSexo( (String) jsonObject.get("sexo") );
alunoVo.setIdade( (Long) jsonObject.get("idade") );
alunoVo.setEstado( (String) jsonObject.get("estado") );
alunoVo.setNota( (Double) jsonObject.get("nota") );
alunoVo.setAtivo( (Boolean) jsonObject.get("ativo") );
//Desta vez a saída será em HTML para apresentação.
response.setContentType("text/html");
response.getOutputStream().print( alunoVo.toString() );
response.getOutputStream().flush();
}
Figura 5. Resultado da execução do Servlet em um navegador WEB.
Conclusão
Como apresentado neste artigo, a biblioteca JSON4J pode simplificar o desenvolvimento de aplicações Java que precisam manipular ou transformar estruturas JSON simples ou complexas, pois a biblioteca JSON4J encapsula toda a complexidade de uma estrutura JSON.
A biblioteca JSON4J pode ser muito útil em aplicações baseadas em AJAX (Asynchronous JavaScript and XML) ou webservices que recebem ou retornam uma estrutura JSON.
Referências
- JSON website
- Visão Geral da biblioteca JSON4J
- Feature Pack for Web 2.0
- Installing the WebSphere Application Server Feature Pack for Web 2.0
- Documentação da biblioteca JSON4J
- What’s new in IBM Rational Application Developer Version 7.5
- Crie um aplicativo da Web baseado em Ajax dinâmico com o WebSphere Application Server Feature Pack para Web 2.0
Sugestão de download: Baixe gratuitamente e avalie o IBM Rational Team Concert – baseado na plataforma Jazz, agora suporta qualquer plano, qualquer processo, qualquer plataforma! Novos modelos de planejamento formal suportam fases de projetos tradicionais, enquanto que novos recursos de gerenciamento de risco podem ser usados por qualquer equipe tradicional, ágil ou híbrida. Você poderá combinar e corresponder implementações para atender a seus ambientes particulares com um único release para todas as plataformas, licenciamento de usuário simples com base em função, sem cobrança do software do servidor e com novos modelos flexíveis de precificação.
Sobre o autor
Marcelo Nascimento é pós graduado em Análise de Sistema pela Universidade Presbiteriana Mackenzie. Atualmente é arquiteto de sistemas J2EE em Global Business Services na IBM Brasil.