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

Java 使用Jackson自定义JSON字段反序列化,java,json,jackson,deserialization,json-deserialization,Java,Json,Jackson,Deserialization,Json Deserialization,我正在使用Jackson反序列化一些JSON,在尝试对其中一个字段使用自定义反序列化程序时遇到了一些问题 class MyClass { private static class SpecialPropertyDeserializer extends JsonDeserializer<SpecialProperty> { @Override public SpecialProperty deserialize(JsonParser js

我正在使用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;
    }
}
我按如下方式调用映射器:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);   
return objectMapper.readValue(input, MyClass.class);
我观察到以下行为:

  • 如果没有特殊属性,则一切正常-即移除所有 代码和JSON中对
    SpecialProperty
    的引用
  • 如果我在JSON中包含
    SpecialProperty
    ,但删除自定义属性 对它进行反序列化,然后它也可以正常工作。选举委员会
    SpecialProperty
    被调用
  • 对于自定义反序列化程序,它不起作用。调用了
    SpecialProperty
    的构造函数,但未调用自定义反序列化器

  • 我做错了什么?

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

    例如,1如果它使用setter设置字段的值,它将在setter上注意到
    @JsonDeserialize

    例如,如果它不使用setter或构造函数直接设置该字段,则会在字段上注意到
    @JsonDeserialize

    如果它在类上,它将倾向于考虑它,除非它被字段或setter上更具体的注释覆盖。我认为这些文件可以更清楚地说明上述细节

    在您的例子中,注释位于
    SpecialProperty
    字段上,但您正在
    MyClass
    构造函数中设置此字段,因此它被忽略

    在这种情况下,您可以将
    @JsonDeserialize
    移动到类上,而不是字段上。在你的情况下,这可能是最简单的解决方案。例如

    @JsonDeserialize(using = MyClass.SpecialPropertyDeserializer.class)
    private static class SpecialProperty {
    
    或者您可以完全跳过注释并在映射器上注册反序列化器。首先在
    MyClass
    中使
    SpecialProperty
    SpecialPropertySerializer
    非私有,然后:

    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(MyClass.SpecialProperty.class, new MyClass.SpecialPropertyDeserializer());
    objectMapper.registerModule(module);
    

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

    您的SpecialProperty是对象吗?如果是,那它是什么样的?它是一个物体,是的。它由类
    SpecialProperty
    表示。有没有一种方法可以只对一个字段使用反序列化器,而不更新POJO?
    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(MyClass.SpecialProperty.class, new MyClass.SpecialPropertyDeserializer());
    objectMapper.registerModule(module);