W3docs

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);   // 2008

Se 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 BuilderEfeito
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ê.

java— editable, runs on the server

O que observar na execução:

  • A primeira linha mostra a serialização: o record Book torna-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 que gson.toJson() produz.
  • A segunda linha mostra a desserialização: analisar esse texto de volta e reconstruir um Book, o mesmo trabalho que gson.fromJson(json, Book.class) faz em uma chamada.
  • Round-trip equal? true prova 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 JSON mostra uma List<Book> renderizada como um array JSON de objetos, a estrutura que você desserializaria com um TypeToken<List<Book>>.
  • O bloco Pretty mostra saída indentada em múltiplas linhas, ilustrando o que GsonBuilder.setPrettyPrinting() oferece em comparação com o padrão compacto.

Prática

Prática
No Gson, por que você precisa de um TypeToken para desserializar um List<Book> em vez de simplesmente passar List.class?
No Gson, por que você precisa de um TypeToken para desserializar um List<Book> em vez de simplesmente passar List.class?
Was this page helpful?