Premiers pas avec la désérialisation personnalisée dans Jackson

1. Vue d'ensemble

Ce tutoriel rapide illustrera comment utiliser Jackson 2 pour désérialiser JSON à l'aide d'un désérialiseur personnalisé .

Si vous voulez creuser plus profondément et apprendre d' autres choses intéressantes que vous pouvez faire avec le Jackson 2 , dirigez-vous vers le didacticiel principal de Jackson.

2. Désérialisation standard

Commençons par définir 2 entités et voyons comment Jackson désérialisera une représentation JSON vers ces entités sans aucune personnalisation:

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

Maintenant, définissons la représentation JSON que nous voulons désérialiser:

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

Et enfin, annulons ce JSON en entités Java:

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

3. Désérialiseur personnalisé sur ObjectMapper

Dans l'exemple précédent, la représentation JSON correspondait parfaitement aux entités java - ensuite, nous simplifierons le JSON:

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

Lorsque vous annulez ceci avec exactement les mêmes entités - par défaut, cela échouera bien sûr:

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

Nous allons résoudre ce problème en effectuant notre propre désérialisation avec un désérialiseur personnalisé :

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

Comme vous pouvez le voir, le désérialiseur fonctionne avec la représentation Jackson standard de JSON - le JsonNode . Une fois que le JSON d'entrée est représenté comme un JsonNode , nous pouvons maintenant en extraire les informations pertinentes et construire notre propre entité Item .

En termes simples, nous devons enregistrer ce désérialiseur personnalisé et désérialiser simplement le JSON normalement:

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. Désérialiseur personnalisé sur la classe

Alternativement, nous pouvons également enregistrer le désérialiseur directement sur la classe :

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

Avec le désérialiseur défini au niveau de la classe, il n'est pas nécessaire de l'enregistrer sur l' ObjectMapper - un mappeur par défaut fonctionnera bien:

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

Ce type de configuration par classe est très utile dans les situations dans lesquelles nous n'avons pas d'accès direct à l' ObjectMapper brut à configurer.

5. Conclusion

Cet article montre comment tirer parti de Jackson 2 pour lire une entrée JSON non standard et comment mapper cette entrée à n'importe quel graphique d'entité Java avec un contrôle total sur le mappage.

L'implémentation de tous ces exemples et extraits de code peut être trouvée dans over sur GitHub - c'est un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.