使用 Jackson 自定义反序列化 JSON 字段

ksl*_*ksl 5 java json jackson deserialization json-deserialization

我正在使用 Jackson 反序列化一些 JSON,并且在尝试对其中一个字段使用自定义反序列化器时遇到了一些麻烦。

class MyClass
{
    private static class SpecialPropertyDeserializer extends JsonDeserializer<SpecialProperty>
    {
        @Override
        public SpecialProperty deserialize(JsonParser jsonParser,
                                           DeserializationContext deserializationContext) throws IOException, JsonProcessingException
        {
            // do some custom deserialisation
        }
    }

    private static class SpecialProperty
    {
        private String m_foo;

        private String m_bar;

        @JsonCreator
        SpecialProperty(@JsonProperty("foo") String foo,
                        @JsonProperty("bar") String bar)
        {
            m_foo = foo;
            m_bar = bar;
        }
    }

    private String m_identifier;

    private String m_version;

    @JsonDeserialize(using = SpecialPropertyDeseializer.class)
    private SpecialProperty m_specialProperty;

    @JsonCreator
    MyClass(@JsonProperty("identifier") String identifier,
            @JsonProperty("version") String version,
            @JsonProperty("specialProperty") SpecialProperty specialProperty)
    {
        m_identifier = identifier;
        m_version = version;
        m_specialProperty = specialProperty;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我要反序列化的 JSON:

{
    "identifier" : "some-id",
    "version"    : "1.7",
    "specialProperty"    : {
        "foo" : "str1",
        "bar" : "str2"
    },
}
Run Code Online (Sandbox Code Playgroud)

我调用映射器如下:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);   
return objectMapper.readValue(input, MyClass.class);
Run Code Online (Sandbox Code Playgroud)

我观察到以下行为:

  1. 没有特殊属性,它一切正常 - 即SpecialProperty从代码和 JSON 中删除所有引用。
  2. 如果我包含SpecialProperty在 JSON 中但删除了它的自定义反序列化器,那么它也可以正常工作。ctor for SpecialProperty被调用。
  3. 使用自定义解串器它不起作用。ctor forSpecialProperty被调用,但自定义解串器不是。

我究竟做错了什么?

Man*_*dis 4

@JsonDeserialize注释可以放置在字段、setter 或类上。如果注释的内容是用来设置值的内容,杰克逊将考虑这一点。

Eg1@JsonDeserialize如果它使用 setter 来设置字段的值,它会注意到 setter。

@JsonDeserializeEg2如果不使用 setter 或构造函数直接设置该字段,它将注意到该字段。

如果它在类上,它会倾向于考虑它,除非它被字段或设置器文档上更具体的注释覆盖。我认为文档对上述细节可能会更清楚。

在您的情况下,您在该字段上有注释SpecialProperty,但您在构造函数中设置该字段MyClass,因此它被忽略。

在这种情况下,您可以@JsonDeserialize在班级上移动,而不是在场地上移动。这可能是您的情况中最简单的解决方案。例如

@JsonDeserialize(using = MyClass.SpecialPropertyDeserializer.class)
private static class SpecialProperty {
Run Code Online (Sandbox Code Playgroud)

或者您可以完全跳过注释并在映射器上注册反序列化器。首先将SpecialProperty其设为SpecialPropertyDeserializer非私有,MyClass然后:

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(MyClass.SpecialProperty.class, new MyClass.SpecialPropertyDeserializer());
objectMapper.registerModule(module);
Run Code Online (Sandbox Code Playgroud)

您还可以删除构造函数,并且将考虑MyClass该字段的当前注释。SpecialProperty