JSON to Java
Java POJO-Klassen aus JSON generieren
JSON-Eingabe
Java-Ausgabe
Was ist die JSON-zu-Java-Klassenkonvertierung?
Die JSON-zu-Java-Klassenkonvertierung nimmt ein rohes JSON-Objekt und erzeugt daraus Plain Old Java Object (POJO)-Definitionen mit privaten Feldern, Gettern und Settern. Java verfügt über kein eingebautes JSON-Typsystem, daher benötigt jede API-Antwort, jede Konfigurationsdatei und jeder Message-Payload eine entsprechende Klasse, bevor man typsicher damit arbeiten kann. Bibliotheken wie Jackson und Gson bilden JSON-Schlüssel über Reflection auf Java-Felder ab, setzen aber voraus, dass die Klassendefinitionen bereits vorhanden sind.
Ein Standard-Java-POJO für die JSON-Deserialisierung deklariert für jeden JSON-Schlüssel ein privates Feld, einen Konstruktor ohne Argumente sowie ein Getter/Setter-Paar pro Feld. Verschachtelte JSON-Objekte werden zu separaten Klassen. Arrays werden zu List<T>-Feldern mit einem java.util.List-Import. Primitive JSON-Typen werden auf Java-Primitive (int, double, boolean) oder deren Wrapper-Typen (Integer, Double, Boolean) abgebildet, wenn sie innerhalb von Generics verwendet werden. Null-Werte werden typischerweise auf Object oder einen nullbaren Referenztyp abgebildet.
Diese Klassendefinitionen von Hand zu schreiben ist repetitiv. Man liest jeden JSON-Schlüssel, ermittelt den Java-Typ aus dem Wert, konvertiert Namenskonventionen von camelCase-JSON zu camelCase-Java-Feldern, erstellt PascalCase-Klassennamen für verschachtelte Objekte und fügt den Getter/Setter-Boilerplate hinzu. Bei einem JSON-Objekt mit 15 Feldern und 3 verschachtelten Objekten bedeutet das: 4 Klassen, 30+ Methoden schreiben und alles konsistent halten. Ein Konverter erledigt das in Millisekunden.
Warum einen JSON-zu-Java-Konverter verwenden?
POJOs manuell aus JSON zu erstellen bedeutet: jedes Feld inspizieren, Typen aus Beispielwerten ableiten, Getter/Setter-Paare schreiben und diesen Prozess für jedes verschachtelte Objekt wiederholen. Ändert sich der API-Vertrag, muss alles per Hand aktualisiert werden. Ein Konverter nimmt diese mechanische Arbeit ab.
JSON-zu-Java-Anwendungsfälle
JSON-zu-Java-Typ-Mapping
Jeder JSON-Wert wird auf einen bestimmten Java-Typ abgebildet. Die folgende Tabelle zeigt, wie der Konverter jeden JSON-Typ in sein Java-Äquivalent übersetzt. Die Spalte Alternative zeigt Wrapper-Typen, die in generischen Kontexten wie List<T> verwendet werden, oder neuere Java-Features wie Records.
| JSON-Typ | Beispiel | Java-Typ | Alternative |
|---|---|---|---|
| string | "hello" | String | String |
| number (integer) | 42 | int | int / Integer |
| number (float) | 3.14 | double | double / Double |
| boolean | true | boolean | boolean / Boolean |
| null | null | Object | Object (or @Nullable String) |
| object | {"k": "v"} | NestedClass | Record (Java 16+) |
| array of strings | ["a", "b"] | List<String> | List<String> |
| array of objects | [{"id": 1}] | List<Item> | List<Item> |
| mixed array | [1, "a"] | List<Object> | List<Object> |
Java-JSON-Annotations-Referenz
Bei der Deserialisierung von JSON mit Jackson oder Gson steuern Annotationen, wie JSON-Schlüssel auf Java-Felder abgebildet werden, wie unbekannte Felder behandelt werden und wie mit null-Werten umgegangen wird. Diese Referenz behandelt die Annotationen, die beim Arbeiten mit generierten POJOs am häufigsten vorkommen.
| Annotation | Zweck | Bibliothek |
|---|---|---|
| @JsonProperty("name") | Maps a JSON key to a Java field with a different name | Jackson |
| @SerializedName("name") | Same as @JsonProperty, but for the Gson library | Gson |
| @JsonIgnoreProperties | Ignores unknown JSON keys during deserialization instead of failing | Jackson |
| @Nullable | Marks a field as accepting null values from JSON input | JSR 305 / JetBrains |
| @NotNull | Enforces that a field must not be null, throws on violation | Bean Validation |
| @JsonFormat(pattern=...) | Defines a date/time format for serialization and deserialization | Jackson |
POJO vs. Record vs. Lombok
Java bietet drei gängige Ansätze, um typisierte Strukturen für JSON-Daten zu definieren. Jeder passt zu einem anderen Projektstil und einer anderen Java-Version. POJOs sind das traditionelle Muster mit der breitesten Kompatibilität. Records reduzieren Boilerplate für unveränderliche Daten. Lombok generiert Getter, Setter und Konstruktoren zur Compile-Zeit über Annotationen.
Code-Beispiele
Diese Beispiele zeigen, wie generierte Java-POJOs mit Jackson für die Deserialisierung verwendet werden, wie Java-Klassen programmgesteuert aus JavaScript und Python erzeugt werden und wie das jsonschema2pojo-CLI-Tool für die Batch-Generierung eingesetzt wird.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private int id;
private String name;
private String email;
private boolean active;
private double score;
private Address address;
private List<String> tags;
// getters and setters omitted for brevity
public static void main(String[] args) throws Exception {
String json = "{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@example.com\",\"active\":true,\"score\":98.5,\"address\":{\"street\":\"123 Main St\",\"city\":\"Springfield\",\"zip\":\"12345\"},\"tags\":[\"admin\",\"user\"]}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println(user.getName()); // -> Alice
}
}
class Address {
private String street;
private String city;
private String zip;
// getters and setters
}// Minimal JSON-to-Java-POJO generator in JS
function jsonToJava(obj, name = "Root") {
const classes = [];
function infer(val, fieldName) {
if (val === null) return "Object";
if (typeof val === "string") return "String";
if (typeof val === "number") return Number.isInteger(val) ? "int" : "double";
if (typeof val === "boolean") return "boolean";
if (Array.isArray(val)) {
const first = val.find(v => v !== null);
if (!first) return "List<Object>";
const elem = infer(first, fieldName);
const boxed = elem === "int" ? "Integer" : elem === "double" ? "Double" : elem === "boolean" ? "Boolean" : elem;
return `List<${boxed}>`;
}
if (typeof val === "object") {
const cls = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
build(val, cls);
return cls;
}
return "Object";
}
function build(obj, cls) {
const fields = Object.entries(obj).map(([k, v]) => {
const type = infer(v, k);
return ` private ${type} ${k};`;
});
classes.push(`public class ${cls} {\n${fields.join("\n")}\n}`);
}
build(obj, name);
return classes.join("\n\n");
}
console.log(jsonToJava({ id: 1, name: "Alice", scores: [98, 85] }, "User"));
// public class User {
// private int id;
// private String name;
// private List<Integer> scores;
// }import json
def json_to_java(obj: dict, class_name: str = "Root") -> str:
classes = []
def infer(val, name):
if val is None:
return "Object"
if isinstance(val, bool):
return "boolean"
if isinstance(val, int):
return "int"
if isinstance(val, float):
return "double"
if isinstance(val, str):
return "String"
if isinstance(val, list):
if not val:
return "List<Object>"
elem = infer(val[0], name)
boxed = {"int": "Integer", "double": "Double", "boolean": "Boolean"}.get(elem, elem)
return f"List<{boxed}>"
if isinstance(val, dict):
cls = name[0].upper() + name[1:]
build(val, cls)
return cls
return "Object"
def build(obj, cls):
fields = [f" private {infer(v, k)} {k};" for k, v in obj.items()]
classes.append(f"public class {cls} {{\n" + "\n".join(fields) + "\n}")
build(obj, class_name)
return "\n\n".join(classes)
data = json.loads('{"id": 1, "name": "Alice", "tags": ["admin"]}')
print(json_to_java(data, "User"))
# public class User {
# private int id;
# private String name;
# private List<String> tags;
# }# Install jsonschema2pojo (requires Java 8+)
# Download from https://github.com/joelittlejohn/jsonschema2pojo
# Generate POJOs from a JSON file
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style jackson2
# Generate with Gson annotations instead
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style gson
# From a JSON string via stdin
echo '{"id": 1, "name": "Alice", "tags": ["admin"]}' | \
jsonschema2pojo --source-type json --annotation-style jackson2 \
--target src/main/java --target-package com.example.model