JSON a Java
Genera clases Java POJO desde JSON
Entrada JSON
Salida Java
¿Qué es la conversión de JSON a clase Java?
La conversión de JSON a clase Java toma un objeto JSON en bruto y genera definiciones de Plain Old Java Object (POJO) con campos privados, getters y setters. Java no tiene un sistema de tipos JSON incorporado, por lo que toda respuesta de API JSON, archivo de configuración o payload de mensajes necesita una clase correspondiente antes de poder trabajar con él de forma segura en cuanto a tipos. Librerías como Jackson y Gson mapean las claves JSON a campos Java mediante reflexión, pero requieren que las definiciones de clase existan primero.
Un POJO Java estándar para la deserialización de JSON declara un campo privado por cada clave JSON, un constructor sin argumentos y un par getter/setter por campo. Los objetos JSON anidados se convierten en clases separadas. Los arrays se convierten en campos List<T> con el import de java.util.List. Los tipos primitivos JSON se mapean a primitivos Java (int, double, boolean) o a sus tipos envolventes (Integer, Double, Boolean) cuando se usan en genéricos. Los valores null se mapean típicamente a Object o a un tipo de referencia que admita null.
Escribir estas definiciones de clase a mano es un trabajo repetitivo. Hay que leer cada clave JSON, determinar el tipo Java a partir del valor, convertir las convenciones de nombres de camelCase JSON a campos Java en camelCase, crear nombres de clase en PascalCase para los objetos anidados y añadir el boilerplate de getters y setters. Para un objeto JSON con 15 campos y 3 objetos anidados, eso implica escribir 4 clases, más de 30 métodos y mantener todo coherente. Un conversor hace esto en milisegundos.
¿Por qué usar un conversor de JSON a Java?
Crear POJOs Java desde JSON de forma manual implica inspeccionar cada campo, inferir tipos a partir de valores de ejemplo, escribir pares getter/setter y repetir el proceso para cada objeto anidado. Cuando el contrato de la API cambia, hay que actualizar todo a mano. Un conversor elimina ese trabajo mecánico.
Casos de uso de JSON a Java
Mapeo de tipos JSON a Java
Cada valor JSON se mapea a un tipo Java específico. La tabla siguiente muestra cómo el conversor traduce cada tipo JSON a su equivalente en Java. La columna Alternativa muestra los tipos envolventes usados en contextos genéricos como List<T>, o las características más recientes de Java como Records.
| Tipo JSON | Ejemplo | 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> |
Referencia de anotaciones Java para JSON
Al deserializar JSON con Jackson o Gson, las anotaciones controlan cómo se mapean las claves JSON a los campos Java, cómo se gestionan los campos desconocidos y cómo se tratan los valores nulos. Esta referencia cubre las anotaciones que encontrarás con más frecuencia al trabajar con POJOs generados.
| Anotación | Propósito | Librería |
|---|---|---|
| @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 tiene tres enfoques habituales para definir estructuras tipadas que almacenen datos JSON. Cada uno encaja en un estilo de proyecto y versión de Java diferente. Los POJOs son el patrón tradicional con mayor compatibilidad. Los Records reducen el boilerplate para datos inmutables. Lombok genera getters, setters y constructores en tiempo de compilación mediante anotaciones.
Ejemplos de código
Estos ejemplos muestran cómo usar los POJOs Java generados con Jackson para la deserialización, cómo generar clases Java mediante programación desde JavaScript y Python, y cómo usar la herramienta CLI jsonschema2pojo para la generación en lote.
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