Leer y escribir JSON en Java con Jackson 3

Jackson es la biblioteca de JSON más usada en Java (es la que usa Spring por dentro). Su versión 3, de octubre de 2025, cambió de paquete (tools.jackson) y simplificó varias cosas. Aquí convertimos records a JSON y de vuelta, y leemos JSON del que no tenemos clase.

De objeto a JSON y de vuelta

// USA lib
import java.util.List;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.core.type.TypeReference;

record Platillo(String nombre, double precio, List<String> ingredientes) {}

void main() {
    var mapper = JsonMapper.builder().build();
    var tacos = new Platillo("Tacos al pastor", 85.0, List.of("cerdo", "piña", "cebolla"));

    String json = mapper.writeValueAsString(tacos);
    IO.println(json);

    Platillo leido = mapper.readValue(json, Platillo.class);
    IO.println(leido.equals(tacos));

    String menu = """
        [{"nombre": "Pozole", "precio": 120, "ingredientes": ["maíz", "cerdo"]},
         {"nombre": "Sopes", "precio": 60, "ingredientes": ["frijol"]}]""";
    List<Platillo> platillos = mapper.readValue(menu, new TypeReference<List<Platillo>>() {});
    IO.println(platillos.size() + " platillos; el primero: " + platillos.getFirst().nombre());
}
salida{"nombre":"Tacos al pastor","precio":85.0,"ingredientes":["cerdo","piña","cebolla"]}
true
2 platillos; el primero: Pozole

Con records no hace falta nada más: Jackson usa los nombres de los componentes como claves. Para leer una lista, TypeReference conserva el tipo genérico que Java borra al compilar (lo explicamos en las rarezas de Java). Y en Jackson 3 las excepciones ya no son comprobadas: no hace falta throws IOException.

JSON sin clase: el árbol de nodos

// USA lib
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.json.JsonMapper;

void main() {
    String json = """
        {"ciudad": "Monterrey", "actual": {"temp": 31.5, "humedad": 40},
         "alertas": [{"tipo": "calor"}, {"tipo": "uv"}]}""";
    JsonNode raiz = JsonMapper.builder().build().readTree(json);
    IO.println(raiz.get("ciudad").asString());
    IO.println(raiz.at("/actual/temp").asDouble());
    for (JsonNode alerta : raiz.get("alertas")) IO.println("alerta: " + alerta.get("tipo").asString());
    IO.println("¿trae viento? " + raiz.has("viento"));
}
salidaMonterrey
31.5
alerta: calor
alerta: uv
¿trae viento? false

readTree convierte cualquier JSON en un árbol que se recorre con get o con rutas como /actual/temp. Es lo práctico para respuestas de APIs de las que solo te interesan dos o tres datos.

Campos que no esperabas

// USA lib
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.json.JsonMapper;

record Usuario(String nombre) {}

void main() {
    String json = "{\"nombre\": \"Ana\", \"edad\": 31}";
    var estricto = JsonMapper.builder().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build();
    try {
        estricto.readValue(json, Usuario.class);
    } catch (Exception e) {
        IO.println("estricto: " + e.getClass().getSimpleName());
    }
    var porOmision = JsonMapper.builder().build();
    IO.println("por omisión: " + porOmision.readValue(json, Usuario.class));
}
salidaestricto: UnrecognizedPropertyException
por omisión: Usuario[nombre=Ana]

Un cambio de Jackson 3 que conviene conocer: por omisión ya no falla si el JSON trae campos que tu clase no tiene (en Jackson 2 sí fallaba). Es lo cómodo para consumir APIs que añaden campos con el tiempo; si necesitas que el JSON sea exactamente el esperado, activa FAIL_ON_UNKNOWN_PROPERTIES.

Las dependencias

Con Maven basta con tools.jackson.core:jackson-databind:3.2.4 (trae jackson-core y jackson-annotations). Para probar estos programas sin Maven, se descargan los tres JAR de Maven Central y se pasan con java -cp "lib/*" Programa.java, que es lo que hicimos aquí con Jackson 3.2.4 y jackson-annotations 2.22: las anotaciones siguen en la rama 2.

Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.