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); // 2008Se 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 builder | Effetto |
|---|---|
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.
Cosa osservare dall'esecuzione:
- La prima riga mostra la serializzazione: il record
Bookdiventa{"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 producegson.toJson(). - La seconda riga mostra la deserializzazione: analizzare quel testo e ricostruire un
Book, lo stesso lavoro chegson.fromJson(json, Book.class)svolge in una sola chiamata. Round-trip equal? truedimostra 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 JSONmostra unaList<Book>resa come array JSON di oggetti, la struttura che si deserializzerebbe con unTypeToken<List<Book>>. - Il blocco
Prettymostra un output indentato su più righe, illustrando ciò cheGsonBuilder.setPrettyPrinting()offre rispetto al default compatto.