JSON in Classe Java
Genera classi Java POJO da JSON
Input JSON
Output Java
Cos'è la conversione da JSON a classe Java?
La conversione da JSON a classe Java prende un oggetto JSON grezzo e produce definizioni Plain Old Java Object (POJO) con campi privati, getter e setter. Java non ha un sistema di tipi JSON integrato, quindi ogni risposta API JSON, file di configurazione o payload di messaggi ha bisogno di una classe corrispondente prima di poterlo usare in modo type-safe. Librerie come Jackson e Gson mappano le chiavi JSON ai campi Java tramite reflection, ma richiedono che le definizioni delle classi esistano prima.
Un POJO Java standard per la deserializzazione JSON dichiara un campo privato per ogni chiave JSON, un costruttore senza argomenti e una coppia getter/setter per campo. Gli oggetti JSON annidati diventano classi separate. Gli array diventano campi List<T> con un import java.util.List. I tipi JSON primitivi si mappano ai primitivi Java (int, double, boolean) o ai loro tipi wrapper (Integer, Double, Boolean) quando usati all'interno dei generics. I valori null si mappano tipicamente a Object o a un tipo riferimento nullable.
Scrivere queste definizioni di classi a mano è ripetitivo. Bisogna leggere ogni chiave JSON, determinare il tipo Java dal valore, convertire le convenzioni di denominazione dal camelCase JSON ai campi Java in camelCase, creare nomi di classe in PascalCase per gli oggetti annidati e aggiungere il codice boilerplate di getter e setter. Per un oggetto JSON con 15 campi e 3 oggetti annidati, significa scrivere 4 classi, 30+ metodi e mantenere tutto coerente. Un convertitore lo fa in millisecondi.
Perché usare un convertitore da JSON a Java?
Creare manualmente POJO Java da JSON significa ispezionare ogni campo, dedurre i tipi dai valori di esempio, scrivere coppie getter/setter e ripetere il processo per ogni oggetto annidato. Quando il contratto API cambia, aggiorni tutto a mano. Un convertitore elimina quel lavoro meccanico.
Casi d'uso di JSON in Java
Mappatura dei tipi da JSON a Java
Ogni valore JSON si mappa a un tipo Java specifico. La tabella seguente mostra come il convertitore traduce ogni tipo JSON nel suo equivalente Java. La colonna Alternativa mostra i tipi wrapper usati in contesti generici come List<T>, o le funzionalità Java più recenti come i Record.
| Tipo JSON | Esempio | Tipo Java | Alternativa |
|---|---|---|---|
| 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> |
Riferimento alle annotazioni JSON Java
Quando si deserializza JSON con Jackson o Gson, le annotazioni controllano come le chiavi JSON si mappano ai campi Java, come vengono gestiti i campi sconosciuti e come vengono trattati i valori null. Questo riferimento copre le annotazioni che incontrerai più spesso quando lavori con POJO generati.
| Annotazione | Scopo | Libreria |
|---|---|---|
| @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 ha tre approcci comuni per definire strutture tipizzate che contengono dati JSON. Ognuno si adatta a un diverso stile di progetto e versione Java. I POJO sono il pattern tradizionale con la più ampia compatibilità. I Record riducono il codice boilerplate per i dati immutabili. Lombok genera getter, setter e costruttori al momento della compilazione tramite annotazioni.
Esempi di codice
Questi esempi mostrano come usare i POJO Java generati con Jackson per la deserializzazione, come produrre classi Java in modo programmatico da JavaScript e Python, e come usare lo strumento CLI jsonschema2pojo per la generazione in batch.
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