JSON do Java
Generuj klasy Java POJO z JSON
Wejście JSON
Wyjście Java
Czym jest konwersja JSON do klas Java?
Konwersja JSON do klas Java polega na przekształceniu surowego obiektu JSON w definicje Plain Old Java Object (POJO) z prywatnymi polami, getterami i setterami. Java nie ma wbudowanego systemu typów JSON, więc każda odpowiedź API, plik konfiguracyjny lub ładunek wiadomości wymaga odpowiedniej klasy, zanim będzie można bezpiecznie typowo z nim pracować. Biblioteki takie jak Jackson i Gson mapują klucze JSON na pola Java za pomocą refleksji, ale wymagają do tego wcześniej istniejących definicji klas.
Standardowy Java POJO do deserializacji JSON deklaruje prywatne pole dla każdego klucza JSON, konstruktor bezargumentowy oraz parę getter/setter dla każdego pola. Zagnieżdżone obiekty JSON stają się osobnymi klasami. Tablice stają się polami List<T> z importem java.util.List. Prymitywne typy JSON mapują się na prymitywy Java (int, double, boolean) lub ich typy opakowań (Integer, Double, Boolean) używane wewnątrz generyków. Wartości null typowo mapują się na Object lub typ referencyjny dopuszczający null.
Ręczne pisanie tych definicji klas jest powtarzalne. Trzeba odczytać każdy klucz JSON, określić typ Java na podstawie wartości, przekonwertować konwencje nazewnicze z camelCase JSON na camelCase pól Java, stworzyć nazwy klas w PascalCase dla zagnieżdżonych obiektów i dodać szablon getterów/setterów. Dla obiektu JSON z 15 polami i 3 zagnieżdżonymi obiektami oznacza to napisanie 4 klas, ponad 30 metod i zachowanie spójności w całym kodzie. Konwerter robi to w milisekundy.
Dlaczego warto używać konwertera JSON do Java?
Ręczne tworzenie Java POJO z JSON wymaga sprawdzania każdego pola, wnioskowania typów z przykładowych wartości, pisania par getter/setter i powtarzania tego procesu dla każdego zagnieżdżonego obiektu. Gdy kontrakt API się zmienia, wszystko aktualizujesz ręcznie. Konwerter eliminuje tę mechaniczną pracę.
Przypadki użycia JSON do Java
Tabela mapowania typów JSON do Java
Każda wartość JSON mapuje się na konkretny typ Java. Poniższa tabela pokazuje, jak konwerter przekształca każdy typ JSON na odpowiednik Java. Kolumna Alternatywa pokazuje typy opakowań używane w kontekstach generycznych jak List<T> lub nowsze funkcje Java, takie jak Records.
| Typ JSON | Przykład | Typ Java | Alternatywa |
|---|---|---|---|
| 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> |
Adnotacje Java JSON — przewodnik
Przy deserializacji JSON za pomocą Jackson lub Gson adnotacje kontrolują sposób mapowania kluczy JSON na pola Java, obsługę nieznanych pól oraz traktowanie wartości null. Ten przewodnik obejmuje adnotacje, które najczęściej napotkasz przy pracy z wygenerowanymi POJO.
| Adnotacja | Zastosowanie | Biblioteka |
|---|---|---|
| @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 a Record a Lombok
Java oferuje trzy popularne podejścia do definiowania typowanych struktur przechowujących dane JSON. Każde pasuje do innego stylu projektu i wersji Java. POJO to tradycyjny wzorzec o najszerszej kompatybilności. Records redukują szablon kodu dla niezmiennych danych. Lombok generuje gettery, settery i konstruktory w czasie kompilacji za pomocą adnotacji.
Przykłady kodu
Te przykłady pokazują, jak używać wygenerowanych Java POJO z Jackson do deserializacji, jak programowo generować klasy Java z JavaScript i Python oraz jak używać narzędzia CLI jsonschema2pojo do generowania wsadowego.
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