Getting Started with Custom Deserialization in Jackson – 在杰克逊中开始使用自定义反序列化

最后修改: 2014年 1月 13日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This quick tutorial will illustrate how to use Jackson 2 to deserialize JSON using a custom Deserializer.

这个快速教程将说明如何使用Jackson 2使用一个定制的解串器来解串JSON。

To dig deeper into other cool things we can do with Jackson 2, head on over to the main Jackson tutorial.

要深入了解我们可以用杰克逊2做的其他很酷的事情,请前往杰克逊主要教程

2. Standard Deserialization

2.标准反序列化

Let’s start by defining two entities and see how Jackson will deserialize a JSON representation to these entities without any customization:

让我们从定义两个实体开始,看看Jackson如何在没有任何定制的情况下对这些实体进行反序列化的JSON表示。

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

Now let’s define the JSON representation we want to deserialize:

现在让我们来定义我们想要反序列化的JSON表示。

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

And finally, let’s unmarshal this JSON to Java Entities:

最后,让我们把这个JSON解读为Java实体。

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

3. Custom Deserializer on ObjectMapper

3.在ObjectMapper上自定义反序列化器

In the previous example, the JSON representation matched the Java entities perfectly.

在前面的例子中,JSON表示法与Java实体完全匹配。

Next, we will simplify the JSON:

接下来,我们将简化JSON。

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

When unmarshalling this to the exact same entities, by default, this will of course fail:

当解除对完全相同的实体的传递时,在默认情况下,这当然会失败。

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: java.io.StringReader@53c7a917; line: 1, column: 43] 
 (through reference chain: org.baeldung.jackson.dtos.Item["createdBy"])

We’ll solve this by doing our own deserialization with a custom Deserializer:

我们将通过使用自定义的反序列化器进行我们自己的反序列化来解决这个问题。

public class ItemDeserializer extends StdDeserializer<Item> { 

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

As we can see, the deserializer is working with the standard Jackson representation of JSON — the JsonNode. Once the input JSON is represented as a JsonNode, we can now extract the relevant information from it and construct our own Item entity.

正如我们所看到的,反序列化器正在使用Jackson的标准JSON表示法 – JsonNode。一旦输入的JSON被表示为JsonNode,我们现在就可以从中提取相关信息并构建我们自己的Item实体。

Simply put, we need to register this custom deserializer and deserialize the JSON normally:

简单地说,我们需要注册这个自定义反序列化器并正常反序列化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. Custom Deserializer on the Class

4.类上的自定义反序列化器

Alternatively, we can also register the deserializer directly on the class:

另外,我们也可以直接在类上注册反序列化器

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

With the deserializer defined at the class level, there is no need to register it on the ObjectMapper — a default mapper will work fine:

由于反序列化器是在类的层次上定义的,所以没有必要在ObjectMapper上注册它–默认的映射器会工作得很好。

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

This type of per-class configuration is very useful in situations in which we may not have direct access to the raw ObjectMapper to configure.

在我们可能无法直接访问原始ObjectMapper来配置的情况下,这种按类配置的类型非常有用。

5. Conclusion

5.结论

This article showed how to leverage Jackson 2 to read nonstandard JSON input as well as how to map that input to any Java entity graph with full control over the mapping.

这篇文章展示了如何利用Jackson 2来读取非标准的JSON输入,以及如何将该输入映射到任何Java实体图,并对映射进行完全控制。

The implementation of all these examples and code snippets can be found over on GitHub. It’s a Maven-based project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现可以在GitHub上找到。这是一个基于Maven的项目,所以应该很容易导入并按原样运行。