Java JSON com Gson
Parse e serialização de JSON em Java com a biblioteca Gson do Google — toJson, fromJson e TypeToken.
JSON é a língua franca das APIs web modernas, e as aplicações Java precisam constantemente converter objetos em JSON e analisar JSON de volta em objetos. Gson é a biblioteca open-source do Google para exatamente isso: um kit de ferramentas pequeno e sem dependências que mapeia objetos Java para texto JSON e vice-versa com quase nenhum boilerplate. Este capítulo mostra como o Gson funciona e os padrões que você usará todos os dias.
Se você é novo no formato em si, comece com a introdução ao JSON; para a principal biblioteca alternativa, veja Java JSON com Jackson.
Adicionando o Gson ao Seu Projeto
O Gson não faz parte do JDK, então você o adiciona como dependência. Com Maven, você o declara no seu pom.xml:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>Com Gradle, a mesma dependência é uma única linha:
implementation 'com.google.code.gson:gson:2.11.0'Tudo o que você faz com o Gson passa por uma única classe de ponto de entrada, Gson. Normalmente você cria uma instância e a reutiliza — ela é thread-safe e barata de compartilhar.
import com.google.gson.Gson;
Gson gson = new Gson();Serializando Objetos para JSON
Converter um objeto Java em texto JSON é chamado de serialização, e o Gson faz isso com toJson(). Você passa qualquer objeto e o Gson percorre seus campos usando reflexão, produzindo uma string JSON. Nenhuma anotação ou configuração é necessária para classes comuns.
class Book {
String title;
String author;
int year;
boolean inStock;
Book(String title, String author, int year, boolean inStock) {
this.title = title;
this.author = author;
this.year = year;
this.inStock = inStock;
}
}
Gson gson = new Gson();
Book b = new Book("Clean Code", "Robert Martin", 2008, true);
String json = gson.toJson(b);
// {"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}Os nomes dos campos tornam-se chaves JSON, e os tipos Java mapeiam para os tipos JSON naturais: String para uma string entre aspas, int/double para um número, boolean para true/false. Um campo null é omitido por padrão.
Desserializando JSON para Objetos
A direção inversa — desserialização — usa fromJson(). Você passa o texto JSON e a Class alvo, e o Gson cria uma instância e preenche os campos correspondendo as chaves JSON aos nomes dos campos.
String json = "{\"title\":\"Clean Code\",\"author\":\"Robert Martin\",\"year\":2008,\"inStock\":true}";
Gson gson = new Gson();
Book b = gson.fromJson(json, Book.class);
System.out.println(b.title); // Clean Code
System.out.println(b.year); // 2008Se uma chave JSON não tem campo correspondente, o Gson a ignora; se um campo não tem chave correspondente, ele é deixado no seu valor padrão (null, 0 ou false). Esse comportamento tolerante torna o Gson resiliente quando uma API adiciona novos campos.
TypeToken para Coleções Genéricas
Por causa do apagamento de tipos, o Java descarta as informações de tipo genérico em tempo de execução, então gson.fromJson(json, List.class) não pode saber que você quer uma List<Book> — ele retornaria uma List de objetos LinkedTreeMap. O Gson resolve isso com TypeToken, que captura o tipo genérico completo para que a desserialização produza os elementos esperados.
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
String json = "[{\"title\":\"Effective Java\",\"year\":2018}]";
Type listType = new TypeToken<List<Book>>(){}.getType();
List<Book> books = gson.fromJson(json, listType);Use um TypeToken sempre que o tipo alvo envolver genéricos — List<T>, Map<K, V> ou combinações aninhadas. Para classes simples e não genéricas, a forma Book.class é suficiente.
Pretty Printing e Configuração Personalizada
O Gson padrão produz JSON compacto de linha única. Para configurar o comportamento, você constrói uma instância com GsonBuilder. A solicitação mais comum é o pretty printing — saída legível por humanos com indentação para logs e arquivos de configuração.
import com.google.gson.GsonBuilder;
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls() // include null fields instead of dropping them
.create();
System.out.println(gson.toJson(b));O GsonBuilder controla muitos outros comportamentos. Alguns que você encontrará com frequência:
| Método do Builder | Efeito |
|---|---|
setPrettyPrinting() | Saída indentada e em múltiplas linhas |
serializeNulls() | Emite campos null em vez de ignorá-los |
setDateFormat(...) | Controla como os valores Date são formatados |
registerTypeAdapter(...) | Conecta um serializador/desserializador personalizado para um tipo |
excludeFieldsWithoutExposeAnnotation() | Serializa apenas campos marcados com @Expose |
Para controle total sobre um tipo, você registra um adaptador personalizado implementando JsonSerializer e/ou JsonDeserializer — útil quando um campo precisa de formatação especial que a reflexão não consegue inferir.
Um Exemplo Prático: Serializar, Analisar e Round-Trip
O Gson em si não está no classpath deste executor, então o programa abaixo demonstra os mesmos conceitos usando apenas o JDK: ele serializa um record para JSON manualmente, analisa o texto de volta nos campos, reconstrói o objeto e confirma que o round-trip é sem perdas. Isso é exatamente o que gson.toJson() e gson.fromJson() automatizam para você.
O que observar na execução:
- A primeira linha mostra a serialização: o record
Booktorna-se{"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}, onde cada campo é uma chave JSON e os tipos mapeiam para suas formas JSON naturais — exatamente o quegson.toJson()produz. - A segunda linha mostra a desserialização: analisar esse texto de volta e reconstruir um
Book, o mesmo trabalho quegson.fromJson(json, Book.class)faz em uma chamada. Round-trip equal? trueprova que a conversão é sem perdas — serializar e depois desserializar produz um objeto igual ao original, a propriedade que todo mapeador JSON busca.- A linha
Array JSONmostra umaList<Book>renderizada como um array JSON de objetos, a estrutura que você desserializaria com umTypeToken<List<Book>>. - O bloco
Prettymostra saída indentada em múltiplas linhas, ilustrando o queGsonBuilder.setPrettyPrinting()oferece em comparação com o padrão compacto.