ジャクソンのカスタム逆シリアル化入門

Jacksonでのカスタムデシリアライゼーションの開始

1. 概要

このクイックチュートリアルでは、Jackson 2を使用してcustom Deserializerを使用してJSONを逆シリアル化する方法を説明します。

さらに深く掘り下げてother cool things you can do with the Jackson 2を学びたい場合は、the main Jackson tutorialに進んでください。

2. 標準の逆シリアル化

2つのエンティティを定義することから始めて、JacksonがカスタマイズなしでJSON表現をこれらのエンティティに逆シリアル化する方法を見てみましょう。

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

次に、逆シリアル化するJSON表現を定義しましょう。

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

そして最後に、このJSONをJavaエンティティにアンマーシャリングしましょう。

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

3. ObjectMapperのカスタムデシリアライザー

前の例では、JSON表現はJavaエンティティに完全に一致しました。次に、JSONを単純化します。

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

これをまったく同じエンティティにアンマーシャリングすると、デフォルトではもちろん失敗します。

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

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

ご覧のとおり、デシリアライザーはJSONの標準的なJackson表現であるJsonNodeを使用しています。 入力JSONがJsonNodeとして表されると、extract the relevant information from itを実行して、独自のItemエンティティを構築できます。

簡単に言えば、register this custom deserializerを実行し、JSONを通常どおり逆シリアル化する必要があります。

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. クラスのカスタムデシリアライザー

または、register the deserializer directly on the class

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

クラスレベルで定義されたデシリアライザーを使用すると、ObjectMapperに登録する必要はありません。デフォルトのマッパーは正常に機能します。

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

このタイプのクラスごとの構成は、構成する生のObjectMapperに直接アクセスできない状況で非常に役立ちます。

5. 結論

この記事では、Jackson 2をread non-standard JSON inputに活用する方法と、マッピングを完全に制御してその入力をJavaエンティティグラフにマッピングする方法を示します。

これらすべての例とコードスニペットcan be found in my github projectの実装–これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。