W3docs

Java JSON com Jackson

Analise, gere e vincule JSON em Java com a biblioteca Jackson — ObjectMapper e data binding.

Jackson é a biblioteca JSON padrão de facto para Java. O JDK não fornece nenhuma API JSON própria, então praticamente toda aplicação Spring, Quarkus ou Micronaut recorre ao Jackson para converter objetos Java em texto JSON e vice-versa. Seu ponto de entrada é uma única classe versátil — ObjectMapper — que lida com as duas tarefas que você sempre precisa: serialização (objeto Java → JSON) e desserialização (JSON → objeto Java).

Se você é novo em JSON com Java, comece com a introdução ao JSON; para uma biblioteca alternativa mais leve, veja o capítulo sobre Gson. Esta página aborda como adicionar o Jackson, os três níveis de sua API, data binding, o modelo de árvore e as anotações que controlam o mapeamento.

Adicionando Jackson ao seu projeto

Jackson não faz parte do JDK, então você o declara como uma dependência. O artefato jackson-databind inclui os outros dois módulos principais (jackson-core e jackson-annotations) transitivamente.

<!-- Maven -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.1</version>
</dependency>
// Gradle
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1'

As três formas de trabalhar com JSON

Jackson expõe os mesmos dados de três maneiras diferentes. Escolha o nível que melhor se adapta à tarefa:

AbordagemTipo principalUse quando
Data bindingObjectMapper.readValue / writeValueVocê tem um POJO ou record que espelha o JSON — o caso mais comum
Modelo de árvoreJsonNode via readTreeA estrutura é dinâmica ou você só precisa de alguns campos
StreamingJsonParser / JsonGeneratorDocumentos grandes onde não é possível manter toda a árvore na memória

Data binding é o que você usa 90% do tempo; os outros dois são alternativas de escape.

Data binding: objetos para JSON e volta

ObjectMapper.writeValueAsString serializa qualquer objeto Java lendo seus getters (ou componentes de record); readValue faz o inverso, associando nomes de campos JSON aos seus campos. Um record é o destino mais limpo — o Jackson 2.12+ se vincula ao seu construtor canônico automaticamente, então você não precisa escrever getters nem um construtor sem argumentos.

import com.fasterxml.jackson.databind.ObjectMapper;

record User(String name, int age, boolean active) {}

ObjectMapper mapper = new ObjectMapper();

// serialize: Java -> JSON
User ada = new User("Ada", 36, true);
String json = mapper.writeValueAsString(ada);
// {"name":"Ada","age":36,"active":true}

// deserialize: JSON -> Java
User back = mapper.readValue(json, User.class);
System.out.println(back.name()); // Ada

Para coleções e genéricos, passe ao Jackson uma TypeReference para que o tipo do elemento sobreviva ao apagamento de tipos:

import com.fasterxml.jackson.core.type.TypeReference;

List<User> users = mapper.readValue(jsonArray, new TypeReference<List<User>>() {});

O modelo de árvore: quando a estrutura é desconhecida

Quando você não tem (ou não quer) uma classe correspondente, analise o JSON em uma árvore genérica JsonNode e navegue por chave. Isso espelha o que um parser manual de Map/List faz, mas com accessors com conhecimento de tipo como asInt() e asText().

import com.fasterxml.jackson.databind.JsonNode;

JsonNode root = mapper.readTree(json);
String name = root.get("name").asText();
int age     = root.get("age").asInt();
JsonNode first = root.get("languages").get(0); // array access by index

Controlando o mapeamento com anotações

Os nomes de campos JSON raramente correspondem perfeitamente às convenções Java. Algumas anotações preenchem essa lacuna sem alterar os nomes dos seus campos:

AnotaçãoEfeito
@JsonProperty("user_name")Mapeia um campo para uma chave JSON diferente
@JsonIgnoreOmite um campo em ambas as direções
@JsonInclude(NON_NULL)Remove campos null da saída
@JsonCreator / @JsonFormatConstrução personalizada / formatação de datas
record Account(
    @JsonProperty("user_name") String userName,
    @JsonIgnore String passwordHash) {}

Um exemplo prático: serializar, analisar e vincular manualmente

Jackson não está no classpath deste executor, então o programa abaixo constrói os mesmos conceitos — um escritor JSON, um parser de descida recursiva em uma árvore Map/List, e vinculação em um record — usando apenas java.util. É exatamente o que o ObjectMapper faz nos bastidores: percorre um grafo de objetos para emitir texto e tokeniza o texto para reconstruir uma árvore.

java— editable, runs on the server

O que extrair da execução:

  • A serialização percorre um grafo de objetos e emite texto. A linha serialized mostra um Map/List aninhado renderizado como {"name":"Ada",...,"languages":["Java","Ada"]} — um array dentro de um objeto. ObjectMapper.writeValueAsString faz a mesma percurso recursivo pelos getters do seu POJO ou pelos componentes de um record.
  • O parsing reconstrói uma árvore genérica primeiro. O tipo em tempo de execução do valor analisado é LinkedHashMap, não User — exatamente o modelo de árvore do Jackson, onde readTree entrega um JsonNode que você navega por chave antes que qualquer classe seja envolvida.
  • Números JSON se tornam números Java, com uma decisão de tipo. O campo age voltou como Integer (42) porque o texto não tinha ponto decimal; o parser escolheu Integer em vez de Double. Jackson faz a escolha idêntica, razão pela qual um campo int se vincula de forma limpa enquanto 3.14 seria interpretado como Double.
  • O acesso ao campo é por nome e a ordem é preservada. Usar LinkedHashMap manteve as chaves na ordem de inserção, então name é lido antes de age. O Jackson preserva a ordem das chaves do objeto da mesma forma, razão pela qual o JSON após uma ida e volta parece com o original.
  • A ida e volta é sem perdas quando o modelo corresponde. A linha final re-serializou a árvore analisada para o mesmo JSON de origem, e o record User tipado vinculou name, age e languages corretamente — o ponto central do data binding: texto entra, objeto sai, texto volta, sem desvios.

Prática

Prática
Com Jackson, você recebe uma resposta JSON cuja estrutura você não controla e só precisa ler dois campos de um documento grande e profundamente aninhado. Qual abordagem é mais adequada?
Com Jackson, você recebe uma resposta JSON cuja estrutura você não controla e só precisa ler dois campos de um documento grande e profundamente aninhado. Qual abordagem é mais adequada?
Was this page helpful?