Introduzione alla deserializzazione personalizzata a Jackson

1. Panoramica

Questo rapido tutorial illustrerà come utilizzare Jackson 2 per deserializzare JSON utilizzando un deserializzatore personalizzato .

Se vuoi approfondire e imparare altre cose interessanti che puoi fare con Jackson 2, vai al tutorial principale di Jackson.

2. Deserializzazione standard

Iniziamo definendo 2 entità e vediamo come Jackson deserializzerà una rappresentazione JSON a queste entità senza alcuna personalizzazione:

public class User { public int id; public String name; } public class Item { public int id; public String itemName; public User owner; }

Ora definiamo la rappresentazione JSON che vogliamo deserializzare:

{ "id": 1, "itemName": "theItem", "owner": { "id": 2, "name": "theUser" } }

E infine, unmarshalling questo JSON in Java Entities:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

3. Deserializzatore personalizzato su ObjectMapper

Nell'esempio precedente, la rappresentazione JSON corrispondeva perfettamente alle entità java, successivamente semplificheremo il JSON:

{ "id": 1, "itemName": "theItem", "createdBy": 2 }

Quando si deseleziona questo per le stesse identiche entità, per impostazione predefinita, questo ovviamente fallirà:

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"])

Lo risolveremo effettuando la nostra deserializzazione con un deserializzatore personalizzato :

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)); } }

Come puoi vedere, il deserializzatore funziona con la rappresentazione standard di Jackson di JSON: JsonNode . Una volta che il JSON di input è rappresentato come JsonNode , ora possiamo estrarre le informazioni rilevanti da esso e costruire la nostra entità Item .

In poche parole, dobbiamo registrare questo deserializzatore personalizzato e deserializzare semplicemente il 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. Deserializzatore personalizzato sulla classe

In alternativa, possiamo anche registrare il deserializzatore direttamente sulla classe :

@JsonDeserialize(using = ItemDeserializer.class) public class Item { ... }

Con il deserializzatore definito a livello di classe, non è necessario registrarlo su ObjectMapper : un mapper predefinito funzionerà bene:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

Questo tipo di configurazione per classe è molto utile in situazioni in cui potremmo non avere accesso diretto all'ObjectMapper grezzo da configurare.

5. conclusione

Questo articolo mostra come sfruttare Jackson 2 per leggere input JSON non standard e come mappare quell'input su qualsiasi grafico di entità java con il pieno controllo sulla mappatura.

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata su GitHub : è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.