Java JSON mit Gson
JSON in Java mit Googles Gson-Bibliothek parsen und serialisieren — toJson, fromJson und TypeToken.
JSON ist die Lingua franca moderner Web-APIs, und Java-Anwendungen müssen ständig Objekte in JSON umwandeln und JSON wieder in Objekte parsen. Gson ist Googles Open-Source-Bibliothek genau dafür: ein kleines, abhängigkeitsfreies Toolkit, das Java-Objekte mit nahezu keinem Boilerplate auf JSON-Text abbildet und umgekehrt. Dieses Kapitel zeigt, wie Gson funktioniert und welche Muster Sie täglich verwenden werden.
Wenn Sie noch neu im Format selbst sind, beginnen Sie mit der JSON-Einführung; für die wichtigste alternative Bibliothek siehe Java JSON mit Jackson.
Gson zum Projekt hinzufügen
Gson ist nicht Teil des JDK, daher fügen Sie es als Abhängigkeit hinzu. Mit Maven deklarieren Sie es in Ihrer pom.xml:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>Mit Gradle ist dieselbe Abhängigkeit eine einzelne Zeile:
implementation 'com.google.code.gson:gson:2.11.0'Alles, was Sie mit Gson tun, läuft über eine einzige Einstiegsklasse: Gson. Normalerweise erstellen Sie eine Instanz und verwenden sie wieder — sie ist thread-sicher und günstig zu teilen.
import com.google.gson.Gson;
Gson gson = new Gson();Objekte in JSON serialisieren
Ein Java-Objekt in JSON-Text umzuwandeln wird Serialisierung genannt, und Gson erledigt das mit toJson(). Sie übergeben ein beliebiges Objekt, und Gson durchläuft seine Felder per Reflection und erzeugt einen JSON-String. Für gewöhnliche Klassen sind keine Annotationen oder Konfigurationen erforderlich.
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}Feldnamen werden zu JSON-Schlüsseln, und Java-Typen werden auf die natürlichen JSON-Typen abgebildet: String auf einen String in Anführungszeichen, int/double auf eine Zahl, boolean auf true/false. Ein null-Feld wird standardmäßig weggelassen.
JSON in Objekte deserialisieren
Die umgekehrte Richtung — Deserialisierung — verwendet fromJson(). Sie übergeben den JSON-Text und die Ziel-Class, und Gson erstellt eine Instanz und befüllt die Felder, indem es JSON-Schlüssel mit Feldnamen abgleicht.
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); // 2008Wenn ein JSON-Schlüssel kein passendes Feld hat, ignoriert Gson ihn; wenn ein Feld keinen passenden Schlüssel hat, bleibt es bei seinem Standardwert (null, 0 oder false). Dieses nachsichtige Verhalten macht Gson widerstandsfähig, wenn eine API neue Felder hinzufügt.
TypeToken für generische Collections
Aufgrund von Type Erasure verwirft Java zur Laufzeit generische Typinformationen, daher kann gson.fromJson(json, List.class) nicht wissen, dass Sie eine List<Book> wollen — es würde eine List von LinkedTreeMap-Objekten zurückgeben. Gson löst dies mit TypeToken, das den vollständigen generischen Typ erfasst, sodass die Deserialisierung die erwarteten Elemente liefert.
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);Verwenden Sie ein TypeToken immer dann, wenn der Zieltyp Generics enthält — List<T>, Map<K, V> oder verschachtelte Kombinationen. Für einfache, nicht-generische Klassen reicht die einfache Form Book.class.
Pretty Printing und benutzerdefinierte Konfiguration
Das Standard-Gson erzeugt kompaktes, einzeiliges JSON. Um das Verhalten zu konfigurieren, erstellen Sie eine Instanz mit GsonBuilder. Die häufigste Anforderung ist Pretty Printing — menschenlesbarer, eingerückter Output für Logs und Konfigurationsdateien.
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 steuert viele weitere Verhaltensweisen. Einige, denen Sie häufig begegnen werden:
| Builder-Methode | Effekt |
|---|---|
setPrettyPrinting() | Eingerückter, mehrzeiliger Output |
serializeNulls() | null-Felder ausgeben statt überspringen |
setDateFormat(...) | Steuert die Formatierung von Date-Werten |
registerTypeAdapter(...) | Benutzerdefinierten Serializer/Deserializer für einen Typ einbinden |
excludeFieldsWithoutExposeAnnotation() | Nur mit @Expose markierte Felder serialisieren |
Für vollständige Kontrolle über einen Typ registrieren Sie einen benutzerdefinierten Adapter, der JsonSerializer und/oder JsonDeserializer implementiert — nützlich, wenn ein Feld eine spezielle Formatierung benötigt, die Reflection nicht ableiten kann.
Ein praktisches Beispiel: Serialisieren, Parsen und Round-Trip
Gson selbst ist im Classpath dieses Runners nicht vorhanden, daher demonstriert das folgende Programm dieselben Konzepte nur mit dem JDK: Es serialisiert einen Record manuell in JSON, parst den Text zurück in Felder, baut das Objekt neu auf und bestätigt, dass der Round-Trip verlustfrei ist. Das ist genau das, was gson.toJson() und gson.fromJson() für Sie automatisieren.
Was man aus der Ausgabe mitnehmen kann:
- Die erste Zeile zeigt die Serialisierung: Der
Book-Record wird zu{"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}, wobei jedes Feld ein JSON-Schlüssel ist und Typen auf ihre natürlichen JSON-Formen abgebildet werden — genau das, wasgson.toJson()produziert. - Die zweite Zeile zeigt die Deserialisierung: den Text zurück parsen und ein
Bookneu aufbauen — derselbe Job, dengson.fromJson(json, Book.class)in einem Aufruf erledigt. Round-trip equal? truebeweist, dass die Konvertierung verlustfrei ist — Serialisieren und anschließendes Deserialisieren ergibt ein Objekt, das dem Original entspricht, die Eigenschaft, die jeder JSON-Mapper anstrebt.- Die Zeile
Array JSONzeigt eineList<Book>als JSON-Array von Objekten, die Struktur, die Sie mit einemTypeToken<List<Book>>deserialisieren würden. - Der
Pretty-Block zeigt eingerückten, mehrzeiligen Output und veranschaulicht, wasGsonBuilder.setPrettyPrinting()im Vergleich zum kompakten Standard bietet.