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

Débuter avec la désérialisation personnalisée à Jackson

1. Vue d'ensemble

Ce tutoriel rapide illustrera comment utiliser Jackson 2 pour désérialiser JSON à l'aide d'uncustom Deserializer.

Si vous voulez creuser plus profondément et apprendreother cool things you can do with the Jackson 2 - allez àthe main Jackson tutorial.

2. Désérialisation standard

Commençons par définir 2 entités et voyons comment Jackson désérialisera une représentation JSON en 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, décomposons ce JSON en entités Java:

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

3. Désérialiseur personnalisé surObjectMapper

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

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

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

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "createdBy" (class org.example.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.example.jackson.dtos.Item["createdBy"])

Nous allons résoudre ce problème en faisantour own deserialization with a custom Deserializer:

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 standard de Jackson de JSON - lesJsonNode. Une fois que le JSON d'entrée est représenté comme unJsonNode, nous pouvons maintenantextract the relevant information from it et construire notre propre entitéItem.

En termes simples, nous devonsregister this custom deserializer 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 aussiregister the deserializer directly on the class:

@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 leObjectMapper - un mappeur par défaut fonctionnera correctement:

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

Ce type de configuration par classe est très utile dans les situations où nous pouvons ne pas avoir un accès direct auxObjectMapperbruts à configurer.

5. Conclusion

Cet article montre comment tirer parti de Jackson 2 enread non-standard JSON input - 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 codecan be found in my github project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.