将JsonDeserialize#contentAs与JsonDeserialize#contentConverter或JsonDeserialize#contentUsing结合使用以进行自定义反序列化

时间:2016-09-09 23:10:19

标签: jackson json-deserialization

JsonDeserialize注释文档中,contentAs字段应该定义“用于反序列化内容的具体类型”。

我试图通过分别扩展StdConverter或StdDeserializer来组合使用它,使用转换器(通过相同注释的contentConverter字段)或JsonDeserializer(通过相同注释的contentUsing字段),以尝试创建一个不可知的自定义反序列化器。 我找不到在这两个类中的任何一个中访问JsonDeserialize#contentAs信息的方法。

我知道我扩展的类有一个类型参数,我只是在那里放了一个Object类。文档说明

  

contentAs具体类型,用于将内容(Collection /数组的元素,Maps的值)值反序列化为,而不是以其他方式声明的类型。必须是声明类型的子类型;否则反序列化器可能抛出异常。

显然我在一些可持久的Class的Collection上应用@JsonDeserializer注释。我想通过知道它的id来反序化每个这样的对象。好吧,如果我只能得到我在@JsonDeserializer#contentAs字段中定义的那种类型......

有人可以告诉我这是否可行吗?

1 个答案:

答案 0 :(得分:0)

毕竟我设法使用 @JsonDeserializer#contentAs 来实现不可知的反序列化器。

在阅读了 com.fasterxml.jackson.databind.JsonDeserializer 的javadoc之后,我得出结论,我的自定义反序列化器应该实现 com.fasterxml.jackson.databind.deser.ContextualDeserializer 界面。

ContextualDeserializer#createContextual(DeserializationContext ctxt,BeanProperty property)的实现中 我终于可以访问集合内容的类类型,我在其上应用了@JsonDeserialize注释, 致电:

ctxt.getContextualType().getRawClass()

注意 com.fasterxml.jackson.databind.JsonDeserializer #deserialize(com.fasterxml.jackson.core.JsonParser,com.fasterxml.jackson。)的实现中进行相同的调用。 databind.DeserializationContext)返回null,因此需要上述接口。

我所要做的就是将返回的类存储在自定义反序列化器的成员字段(类型为&lt;?&gt;)中,并在执行 JsonDeserializer #deserialize()<时使用它/ EM>

唯一需要检查的是线程之间是否共享此自定义反序列化器的实例。我只做了一些小检查;我对两个不同类型的不同集合使用了相同的实现。我观察到 ContextualDeserializer #creinContextual(DeserializationContext ctxt,BeanProperty属性)被调用一次(在多个反序列化调用中),用于每个要反序列化的不同类型。在调试期间检查后,似乎同一个反序列化器对象用于相同类型。在我的情况下,由于我在成员字段中存储的是这种类型本身,我不介意是否使用相同的反序列化器来反序列化相同的 java类型,因为它们 应该 包含相同的值。所以我们也清楚这方面。

编辑:我似乎只需要将 com.fasterxml.jackson.databind.deser.std.StdDeserializer #_valueClass 值更新为现在已知的类。由于它是最终的,因为 ContextualDeserializer#createContextual(DeserializationContext ctxt,BeanProperty属性)返回一个实际使用的JsonSerializer对象, 而不是返回&#34; 这个&#34;序列化程序我可以创建一个新的,在构造函数中传递发现的类,它实际上将 StdDeserializer#_valueClass 设置为我真正想要的类,并且我已经完成了所有设置!

最后,注意我没有必要使用 @JsonDeserializer #intentAs 注释字段,因为我从 ctxt.getContextualType获取值( ).getRawClass()语句在 ContextualDeserializer#createContextual(DeserializationContext ctxt,BeanProperty property)实现