如何使用Jackson BeanDeserializerModifier?

时间:2018-01-22 21:07:47

标签: jackson deserialization

我正在尝试实现自定义反序列化器。 因为我只想向默认的反序列化器添加功能,所以我尝试在我的自定义反序列化器中存储默认的反序列化器:我想使用默认值来反序列化json,然后添加其他信息。

我正在尝试使用BeanDeserializerModifier来注册自定义反序列化器。

SimpleModule module = new SimpleModule("ModelModule", Version.unknownVersion());

module.setDeserializerModifier(new BeanDeserializerModifier() {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        JsonDeserializer<?> configuredDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);
        if (Document.class.isAssignableFrom(beanDesc.getBeanClass())) {
            logger.debug("Returning custom deserializer for documents");

            configuredDeserializer = new DocumentDeserializer(configuredDeserializer, (Class<Document>)beanDesc.getBeanClass());
        } 

        return configuredDeserializer;
    }
});

如您所见,如果要生成的对象是&#34; Document&#34;,我正在修改反序列化器,返回自定义反序列化器。我将默认的反序列化器传递给构造函数,以便以后可以使用它。

当我尝试反序列化时,杰克逊因错误而失败:

No _valueDeserializer assigned(..)

我已经调查过,似乎默认的反序列化器没有为其属性提供正确的反序列化器:对于所有属性,它使用的是反序列化器FailingDeserializer,当然,它会失败并返回上面提到的错误。这个反序列化器应该被替换,但它不是。

看来,在调用方法modifyDeserializer之后,Jackson完成了配置。

我使用的自定义反序列化器是:

@SuppressWarnings("serial")
public class DocumentDeserializer extends StdDeserializer<Document> {
    private JsonDeserializer<?> defaultDeserializer;
    private DocumentDeserializer(JsonDeserializer<?> defaultDeserializer, Class<? extends Document> clazz) {
        super(clazz);
        this.defaultDeserializer = defaultDeserializer;
    }

    @Override
    public Document deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Document documentDeserialized = (Document) defaultDeserializer.deserialize(jp, ctxt);
        /* I want to modify the documentDeserialized before returning it */
        return documentDeserialized;
    }
}

更新 我使用不同的反序列化器解决了这个问题:

public class CustomDeserializerModifier extends BeanDeserializerModifier {
    private static final Logger logger = Logger.getLogger(CustomDeserializerModifier.class);

    public CustomDeserializerModifier (Factory factory) {
        this.factory = factory;
    }

    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        JsonDeserializer<?> configuredDeserializer;
        if (CustomDeserializedNode.class.isAssignableFrom(beanDesc.getBeanClass())) {
            Converter<Object, Object> conv = beanDesc.findDeserializationConverter();
            JavaType delegateType = conv.getInputType(config.getTypeFactory());
            configuredDeserializer = new CustomDeserializedNodeDeserializer(conv, delegateType, (JsonDeserializer<Document>) deserializer, 
                    (Class<? extends CustomDocument<?>>)beanDesc.getBeanClass());
        } else {
            configuredDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);
        }

        return configuredDeserializer;
    }

    @SuppressWarnings("serial")
    public class CustomDeserializedNodeDeserializer extends StdDelegatingDeserializer<Object> {
        private Class<? extends CustomDocument<?>> beanClass;
        public CustomDeserializedNodeDeserializer(Converter<Object,Object> converter,
                JavaType delegateType, JsonDeserializer<Document> delegateDeserializer, Class<? extends CustomDocument<?>> beanClass) {
            super(converter, delegateType, delegateDeserializer);
            this.beanClass = beanClass;
        }

        @Override
        public CustomDeserializedNode deserialize(JsonParser jp, DeserializationContext ctxt)

                throws IOException, JsonProcessingException {
            CustomDeserializedNode node = (CustomDeserializedNode)factory.createCustomDocument(beanClass);
            CustomDeserializedNode documentDeserialized = (Document) super.deserialize(jp, ctxt, node);

            return documentDeserialized;
        }
    }

}

可能会扩展StdDelegatingDeserializer来执行@StaxMan的建议。

1 个答案:

答案 0 :(得分:3)

这应该添加到FAQ中,但您需要做的是实现2个接口:

  • ResolvableDeserializer(方法resolve(...)
  • ContextualDeserializer(方法createContextual(...)

并将这些调用委托给defaultDeserializer,以防它实现一个或两个接口。这些是解串器初始化所必需的;特别是ContextualDeserializer,通过它可以为反序列化器提供属性注释。 ResolvableDeserializer使用BeanDeserializer来获取其拥有的属性的反序列化程序(如果有);这是可能会提到_valueDeserializer的地方。