我在 Jackson 的自定义反序列化器中遇到了问题 . 我想访问默认的序列化程序来填充我反序列化的对象 . 在人口之后,我将做一些自定义的事情,但首先我想用默认的jackson行为反序列化对象 .
这是我目前的代码 .
public class UserEventDeserializer extends StdDeserializer<User> {
private static final long serialVersionUID = 7923585097068641765L;
public UserEventDeserializer() {
super(User.class);
}
@Override
@Transactional
public User deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
User deserializedUser = null;
deserializedUser = super.deserialize(jp, ctxt, new User());
// The previous line generates an exception java.lang.UnsupportedOperationException
// Because there is no implementation of the deserializer.
// I want a way to access the default spring deserializer for my User class.
// How can I do that?
//Special logic
return deserializedUser;
}
}
我需要的是一种初始化默认反序列化器的方法,这样我就可以在开始我的特殊逻辑之前预先填充我的POJO .
从自定义反序列化器中调用反序列化时,无论我如何构造序列化器类,都会从当前上下文调用该方法 . 因为我的POJO中有注释 . 这会导致Stack Overflow异常,原因很明显 . 我已经尝试初始化beandeserializer,但是这个过程非常复杂,我还没有找到正确的方法来完成它 . 我也尝试重载注释内部跟踪器无济于事,认为它可以帮助我忽略DeserializerContext中的注释 . 最后它接缝我可能使用JsonDeserializerBuilders取得了一些成功,虽然这要求我做一些神奇的东西来从 Spring 天获得应用程序上下文 . 我将不胜感激,这可能会让我找到一个更清晰的解决方案,例如如何在不读取JsonDeserializer注释的情况下构建反序列化上下文 .
8 回答
正如StaxMan已经建议你可以写一个
BeanDeserializerModifier
并通过SimpleModule
注册它 . 以下示例应该有效:有几种方法可以做到这一点,但要做到这一点涉及更多的工作 . 基本上你不能使用子类,因为信息默认的反序列化需要是从类定义构建的 .
所以你最有可能使用的是构造
BeanDeserializerModifier
,通过Module
接口注册(使用SimpleModule
) . 您需要定义/覆盖modifyDeserializer
,并且对于您要添加自己的逻辑(类型匹配)的特定情况,构造您自己的反序列化器,传递您给出的默认反序列化器 . 然后在deserialize()
方法中,您可以委托调用,获取结果对象 .或者,如果您必须实际创建并填充对象,则可以执行此操作并调用带有第三个参数的
deserialize()
的重载版本;反序列化的对象 .可能有效(但不是100%肯定)的另一种方法是指定
Converter
object(@JsonDeserialize(converter=MyConverter.class)
) . 这是Jackson 2.2的新功能 . 在你的情况下,转换器实际上不会转换类型,但是简化修改对象:但是我不知道是否会让你完全按照自己的意愿行事,因为默认的反序列化器会先调用,然后才会调用Converter
.DeserializationContext
有一个你可以使用的readValue()
方法 . 这应该适用于默认的反序列化器和您拥有的任何自定义反序列化器 .只需确保在要读取的
JsonNode
级别上调用traverse()
以检索JsonParser
以传递给readValue()
.如果您可以声明额外的User类,那么您只需使用注释即可实现它
对我来说更简单的解决方案是添加另一个
ObjectMapper
的bean并使用它反序列化对象(感谢https://stackoverflow.com/users/1032167/varren注释) - 在我的情况下,我有兴趣反序列化为其id(一个int)或整个对象https://stackoverflow.com/a/46618193/986160对于需要通过自定义反序列化器的每个实体,我需要在我的情况下在Spring Boot App的全局
ObjectMapper
bean中配置它(例如Category
):我在https://stackoverflow.com/a/51927577/14731找到了一个答案,它比可接受的答案更具可读性 .
它真的不容易 .
我不习惯使用
BeanSerializerModifier
,因为它强制在中心ObjectMapper
中声明一些行为更改,而不是在自定义反序列化器本身中,并且实际上它是使用JsonSerialize
注释实体类的并行解决方案 . 如果你觉得它的方式相似,你可能会在这里感谢我的回答:https://stackoverflow.com/a/43213463/653539在Tomáš Záluský has suggested的情况下,如果不希望使用
BeanDeserializerModifier
,您可以使用BeanDeserializerFactory
自己构造默认的反序列化器,尽管需要一些额外的设置 . 在上下文中,此解决方案看起来如下: