W3docs

Java JSON con Gson

Analizza e serializza JSON in Java con la libreria Gson di Google — toJson, fromJson e TypeToken.

JSON è la lingua franca delle moderne API web, e le applicazioni Java devono costantemente trasformare oggetti in JSON e ricavare oggetti dal JSON. Gson è la libreria open-source di Google pensata proprio per questo: un toolkit compatto e senza dipendenze che mappa oggetti Java in testo JSON e viceversa con pochissimo codice ridondante. Questo capitolo mostra come funziona Gson e i pattern che utilizzerai ogni giorno.

Se non conosci ancora il formato, inizia con l'introduzione a JSON; per la libreria alternativa principale, consulta Java JSON con Jackson.

Aggiungere Gson al Progetto

Gson non fa parte del JDK, quindi va aggiunto come dipendenza. Con Maven lo dichiari nel tuo pom.xml:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

Con Gradle la stessa dipendenza è una singola riga:

implementation 'com.google.code.gson:gson:2.11.0'

Tutto ciò che fai con Gson passa per un'unica classe d'ingresso, Gson. Di norma si crea un'istanza e la si riutilizza — è thread-safe e poco costosa da condividere.

import com.google.gson.Gson;

Gson gson = new Gson();

Serializzare Oggetti in JSON

Trasformare un oggetto Java in testo JSON si chiama serializzazione, e Gson la esegue con toJson(). Gli passi qualsiasi oggetto e Gson ne percorre i campi tramite reflection, producendo una stringa JSON. Per le classi ordinarie non sono richieste annotazioni né configurazioni.

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}

I nomi dei campi diventano chiavi JSON, e i tipi Java vengono mappati ai tipi JSON naturali: String in una stringa tra virgolette, int/double in un numero, boolean in true/false. Un campo null viene omesso per impostazione predefinita.

Deserializzare JSON in Oggetti

La direzione inversa — la deserializzazione — usa fromJson(). Si passa il testo JSON e la Class di destinazione, e Gson crea un'istanza e riempie i campi abbinando le chiavi JSON ai nomi dei campi.

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 una chiave JSON non ha un campo corrispondente, Gson la ignora; se un campo non ha una chiave corrispondente, viene lasciato al suo valore predefinito (null, 0 o false). Questo comportamento permissivo rende Gson robusto quando un'API aggiunge nuovi campi.

TypeToken per le Collezioni Generiche

A causa della type erasure, Java elimina le informazioni sui tipi generici a runtime, quindi gson.fromJson(json, List.class) non può sapere che vuoi una List<Book> — restituirebbe una List di oggetti LinkedTreeMap. Gson risolve questo con TypeToken, che cattura il tipo generico completo affinché la deserializzazione produca gli elementi attesi.

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

Usa un TypeToken ogni volta che il tipo di destinazione coinvolge generici — List<T>, Map<K, V> o combinazioni annidate. Per classi semplici e non generiche, la forma Book.class è sufficiente.

Pretty Printing e Configurazione Personalizzata

Il Gson predefinito produce JSON compatto su una sola riga. Per configurare il comportamento si costruisce un'istanza con GsonBuilder. La richiesta più comune è il pretty printing — output indentato e leggibile per log e file di configurazione.

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

GsonBuilder controlla molti altri comportamenti. Alcuni che incontrerai spesso:

Metodo del builderEffetto
setPrettyPrinting()Output indentato su più righe
serializeNulls()Emette i campi null invece di ometterli
setDateFormat(...)Controlla come vengono formattati i valori Date
registerTypeAdapter(...)Inserisce un serializzatore/deserializzatore personalizzato per un tipo
excludeFieldsWithoutExposeAnnotation()Serializza solo i campi contrassegnati con @Expose

Per il pieno controllo su un tipo, si registra un adapter personalizzato che implementa JsonSerializer e/o JsonDeserializer — utile quando un campo richiede una formattazione speciale che la reflection non può inferire.

Esempio Pratico: Serializzare, Analizzare e Round-Trip

Gson non è nel classpath di questo runner, quindi il programma seguente dimostra gli stessi concetti usando solo il JDK: serializza un record in JSON manualmente, analizza il testo di ritorno nei campi, ricostruisce l'oggetto e verifica che il round-trip sia privo di perdite. È esattamente ciò che gson.toJson() e gson.fromJson() automatizzano per te.

java— editable, runs on the server

Cosa osservare dall'esecuzione:

  • La prima riga mostra la serializzazione: il record Book diventa {"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}, dove ogni campo è una chiave JSON e i tipi vengono mappati nelle forme JSON naturali — esattamente ciò che produce gson.toJson().
  • La seconda riga mostra la deserializzazione: analizzare quel testo e ricostruire un Book, lo stesso lavoro che gson.fromJson(json, Book.class) svolge in una sola chiamata.
  • Round-trip equal? true dimostra che la conversione è priva di perdite — serializzare e poi deserializzare produce un oggetto uguale all'originale, la proprietà che ogni mapper JSON mira a garantire.
  • La riga Array JSON mostra una List<Book> resa come array JSON di oggetti, la struttura che si deserializzerebbe con un TypeToken<List<Book>>.
  • Il blocco Pretty mostra un output indentato su più righe, illustrando ciò che GsonBuilder.setPrettyPrinting() offre rispetto al default compatto.

Esercitazione

Pratica
In Gson, perché serve un TypeToken per deserializzare una List<Book> invece di passare semplicemente List.class?
In Gson, perché serve un TypeToken per deserializzare una List<Book> invece di passare semplicemente List.class?
Was this page helpful?