W3docs

Java JSON con Jackson

Analiza, genera y vincula JSON en Java con la biblioteca Jackson — ObjectMapper y enlace de datos.

Jackson es la biblioteca JSON estándar de facto para Java. El JDK no incluye ninguna API JSON propia, por lo que casi todas las aplicaciones Spring, Quarkus o Micronaut recurren a Jackson para convertir objetos Java en texto JSON y viceversa. Su punto de entrada es una única clase de trabajo — ObjectMapper — que se encarga de las dos tareas que siempre se necesitan: serialización (objeto Java → JSON) y deserialización (JSON → objeto Java).

Si eres nuevo en JSON en Java, comienza con la introducción a JSON; para una biblioteca alternativa más ligera, consulta el capítulo de Gson. Esta página cubre cómo añadir Jackson, los tres niveles de su API, el enlace de datos, el modelo de árbol y las anotaciones que controlan el mapeo.

Agregar Jackson a tu proyecto

Jackson no forma parte del JDK, por lo que debes declararlo como dependencia. El artefacto jackson-databind incluye de forma transitiva los otros dos módulos principales (jackson-core y jackson-annotations).

<!-- Maven -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.1</version>
</dependency>
// Gradle
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1'

Las tres formas de trabajar con JSON

Jackson expone los mismos datos de tres maneras distintas. Elige el nivel que se ajuste a la tarea:

EnfoqueTipo principalÚsalo cuando
Enlace de datosObjectMapper.readValue / writeValueTienes un POJO o record que refleja el JSON — el caso más común
Modelo de árbolJsonNode vía readTreeLa forma es dinámica o solo necesitas unos pocos campos
StreamingJsonParser / JsonGeneratorDocumentos muy grandes donde no puedes mantener todo el árbol en memoria

El enlace de datos es lo que se usa el 90% del tiempo; los otros dos son escotillas de escape.

Enlace de datos: objetos a JSON y viceversa

ObjectMapper.writeValueAsString serializa cualquier objeto Java leyendo sus getters (o los componentes del record); readValue hace lo contrario, haciendo coincidir los nombres de campos JSON con tus campos. Un record es el destino más limpio — Jackson 2.12+ se enlaza a su constructor canónico automáticamente, por lo que no necesitas escribir getters ni un constructor sin argumentos.

import com.fasterxml.jackson.databind.ObjectMapper;

record User(String name, int age, boolean active) {}

ObjectMapper mapper = new ObjectMapper();

// serialize: Java -> JSON
User ada = new User("Ada", 36, true);
String json = mapper.writeValueAsString(ada);
// {"name":"Ada","age":36,"active":true}

// deserialize: JSON -> Java
User back = mapper.readValue(json, User.class);
System.out.println(back.name()); // Ada

Para colecciones y genéricos, pasa a Jackson un TypeReference para que el tipo de elemento sobreviva al borrado de tipos:

import com.fasterxml.jackson.core.type.TypeReference;

List<User> users = mapper.readValue(jsonArray, new TypeReference<List<User>>() {});

El modelo de árbol: cuando la forma es desconocida

Cuando no tienes (o no quieres) una clase correspondiente, analiza el JSON en un árbol genérico JsonNode y navega por él con claves. Esto imita lo que hace un analizador manual de Map/List, pero con accesores con reconocimiento de tipos como asInt() y asText().

import com.fasterxml.jackson.databind.JsonNode;

JsonNode root = mapper.readTree(json);
String name = root.get("name").asText();
int age     = root.get("age").asInt();
JsonNode first = root.get("languages").get(0); // array access by index

Controlar el mapeo con anotaciones

Los nombres de campos JSON raramente coinciden perfectamente con las convenciones de Java. Un puñado de anotaciones cierra la brecha sin cambiar los nombres de tus campos:

AnotaciónEfecto
@JsonProperty("user_name")Mapea un campo a una clave JSON diferente
@JsonIgnoreOmite un campo en ambas direcciones
@JsonInclude(NON_NULL)Elimina los campos null de la salida
@JsonCreator / @JsonFormatConstrucción personalizada / formato de fecha
record Account(
    @JsonProperty("user_name") String userName,
    @JsonIgnore String passwordHash) {}

Un ejemplo completo: serializar, analizar y enlazar manualmente

Jackson no está en el classpath de este ejecutor, por lo que el programa a continuación construye los mismos conceptos — un escritor JSON, un analizador de descenso recursivo en un árbol Map/List, y el enlace en un record — usando solo java.util. Es exactamente lo que ObjectMapper hace internamente: recorrer un gráfico de objetos para emitir texto, y tokenizar texto para reconstruir un árbol.

java— editable, runs on the server

Lo que hay que aprender de la ejecución:

  • La serialización recorre un gráfico de objetos y emite texto. La línea serialized muestra un Map/List anidado renderizado como {"name":"Ada",...,"languages":["Java","Ada"]} — un array dentro de un objeto. ObjectMapper.writeValueAsString hace el mismo recorrido recursivo sobre los getters de tu POJO o los componentes de un record.
  • El análisis reconstruye primero un árbol genérico. El tipo en tiempo de ejecución del valor analizado es LinkedHashMap, no User — exactamente el modelo de árbol de Jackson, donde readTree te da un JsonNode que navegas por clave antes de que intervenga ninguna clase.
  • Los números JSON se convierten en números Java, con una decisión de tipo. El campo age volvió como un Integer (42) porque el texto no tenía punto decimal; el analizador eligió Integer sobre Double. Jackson toma la decisión idéntica, razón por la cual un campo int se enlaza limpiamente mientras que 3.14 llegaría como un Double.
  • El acceso a los campos es por nombre y el orden se preserva. Usar LinkedHashMap mantuvo las claves en orden de inserción, por lo que name se lee antes que age. Jackson preserva el orden de las claves del objeto de la misma manera, razón por la cual el JSON procesado en un viaje de ida y vuelta se ve igual que el original.
  • El viaje de ida y vuelta es sin pérdida cuando el modelo coincide. La última línea re-serializó el árbol analizado al mismo JSON del que vino, y el User record tipado enlazó name, age y languages correctamente — el punto central del enlace de datos: texto dentro, objeto fuera, texto de vuelta, sin deriva.

Práctica

Práctica
Con Jackson, recibes una respuesta JSON cuya estructura no controlas y solo necesitas leer dos campos de un documento grande y profundamente anidado. ¿Qué enfoque se adapta mejor?
Con Jackson, recibes una respuesta JSON cuya estructura no controlas y solo necesitas leer dos campos de un documento grande y profundamente anidado. ¿Qué enfoque se adapta mejor?
Was this page helpful?