1. Información general
Este tutorial rápido ilustrará cómo usar Jackson 2 para deserializar JSON usando un deserializador personalizado .
Si desea profundizar y aprender otras cosas interesantes que puede hacer con Jackson 2 , diríjase al tutorial principal de Jackson.
2. Deserialización estándar
Comencemos por definir 2 entidades y veamos cómo Jackson deserializará una representación JSON a estas entidades sin ninguna personalización:
public class User { public int id; public String name; } public class Item { public int id; public String itemName; public User owner; }
Ahora, definamos la representación JSON que queremos deserializar:
{ "id": 1, "itemName": "theItem", "owner": { "id": 2, "name": "theUser" } }
Y finalmente, desarmemos este JSON a Entidades Java:
Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);
3. Deserializador personalizado en ObjectMapper
En el ejemplo anterior, la representación JSON coincidía perfectamente con las entidades java; a continuación, simplificaremos el JSON:
{ "id": 1, "itemName": "theItem", "createdBy": 2 }
Al deshacer esto para las mismas entidades exactas, de forma predeterminada, esto, por supuesto, fallará:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "createdBy" (class org.baeldung.jackson.dtos.Item), not marked as ignorable (3 known properties: "id", "owner", "itemName"]) at [Source: [email protected]; line: 1, column: 43] (through reference chain: org.baeldung.jackson.dtos.Item["createdBy"])
Resolveremos esto haciendo nuestra propia deserialización con un deserializador personalizado :
public class ItemDeserializer extends StdDeserializer { public ItemDeserializer() { this(null); } public ItemDeserializer(Class vc) { super(vc); } @Override public Item deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); int id = (Integer) ((IntNode) node.get("id")).numberValue(); String itemName = node.get("itemName").asText(); int userId = (Integer) ((IntNode) node.get("createdBy")).numberValue(); return new Item(id, itemName, new User(userId, null)); } }
Como puede ver, el deserializador está trabajando con la representación estándar de Jackson de JSON: JsonNode . Una vez que el JSON de entrada se representa como un JsonNode , ahora podemos extraer la información relevante de él y construir nuestra propia entidad Item .
En pocas palabras, necesitamos registrar este deserializador personalizado y simplemente deserializar el JSON normalmente:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(Item.class, new ItemDeserializer()); mapper.registerModule(module); Item readValue = mapper.readValue(json, Item.class);
4. Deserializador personalizado en la clase
Alternativamente, también podemos registrar el deserializador directamente en la clase :
@JsonDeserialize(using = ItemDeserializer.class) public class Item { ... }
Con el deserializador definido a nivel de clase, no es necesario registrarlo en ObjectMapper ; un asignador predeterminado funcionará bien:
Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);
Este tipo de configuración por clase es muy útil en situaciones en las que es posible que no tengamos acceso directo al ObjectMapper sin procesar para configurar.
5. Conclusión
Este artículo muestra cómo aprovechar Jackson 2 para leer una entrada JSON no estándar y cómo asignar esa entrada a cualquier gráfico de entidad Java con control total sobre la asignación.
La implementación de todos estos ejemplos y fragmentos de código se puede encontrar en GitHub : es un proyecto basado en Maven, por lo que debería ser fácil de importar y ejecutar como está.