Jackson 将JsonDeserialize#contentAs与JsonDeserialize#contentConverter或JsonDeserialize#contentUsing结合起来进行自定义反序列化

Jackson 将JsonDeserialize#contentAs与JsonDeserialize#contentConverter或JsonDeserialize#contentUsing结合起来进行自定义反序列化,jackson,json-deserialization,Jackson,Json Deserialization,在注释文档中,contentAs字段应该定义“反序列化内容的具体类型” 我尝试将其与转换器(通过同一注释的contentConverter字段)或JsonDeserializer(通过同一注释的contentUsing字段)结合使用,分别扩展StdConverter或StdDeserializer,试图创建一个不可知的自定义反序列化器。 在这两个类中,我找不到访问JsonDeserialize#contentAs信息的方法 我知道我扩展的类有一个类型参数,我只是在那里放了一个对象类。文件状态 c

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

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

我知道我扩展的类有一个类型参数,我只是在那里放了一个对象类。文件状态

contentAs具体类型,将内容(集合/数组的元素、映射的值)反序列化为值,而不是以其他方式声明的类型。必须是声明类型的子类型;否则,反序列化程序可能会引发异常

显然,我正在对某个持久类的集合应用@JsonDeserializer注释。我想反序列化每个这样的对象,只需要知道它的id。好吧,如果我只能得到我在@JsonDeserializer#contentAs字段中定义的类型


有人能告诉我这是否可能吗?

我成功地实现了不可知的反序列化程序,毕竟没有使用@JsonDeserializer#contentAs

在阅读了com.fasterxml.jackson.databind.JsonDeserializer的javadocs之后,我得出结论,我的自定义反序列化程序应该实现com.fasterxml.jackson.databind.deser.ContextualDeserializer接口

在ContextualDeserializer#createContext(反序列化上下文ctxt,BeanProperty属性)的实现内部 我终于可以访问集合内容的类类型,我在其上应用了@JsonDeserialize注释, 致电:

ctxt.getContextualType().getRawClass()
请注意com.fasterxml.jackson.databind.JsonDeserializer#反序列化(com.fasterxml.jackson.core.JsonParser,com.fasterxml.jackson.databind.DeserializationContext)实现中的同一调用返回null,因此需要上述接口

然后,我所要做的就是将返回的类存储在自定义反序列化程序的成员字段(类型为class<?>)中,并将其用于执行JsonDeserializer#deserialize()

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

编辑:看来我所要做的就是将com.fasterxml.jackson.databind.desr.std.StdDeserializer##u valueClass值更新为现在已知的类。由于它是最终的,而且由于ContextualDeserializer#CreateContext(反序列化上下文ctxt,BeanProperty属性)返回实际使用的JsonSerializer对象, 不用返回“this”序列化程序,我可以创建一个新的序列化程序,在构造函数中传递发现的类,这实际上将StdDeserializer##u valueClass设置为我真正想要的类,我已经准备好了


最后,请注意,当我从ContextualDeserializer\createContext(反序列化上下文ctxt,BeanProperty属性)中的ctxt.getContextAltype().getRawClass()语句获取值时,我不必使用@JsonDeserializer#contentAs注释字段实施

我认为你应该试着解释你想要实现什么,而不是解释你是如何实现的。通过这种方式,可以更容易地帮助找到一种获得结果的方法:你目前的方法可能不是一个好方法。在这种情况下,解释您试图反序列化的值的Java类(作为POJO的属性)会有很大帮助。@StaxMan“我试图将其结合使用,…,试图创建一个不可知的自定义反序列化器。”然后:“我想只通过知道其id来反序列化每个这样的对象。”(我可以通过反射来跟踪id)。我认为这涵盖了“什么”部分,我不确定“不可知的自定义反序列化程序”很清楚,没有进一步解释:我可以从进一步的讨论中猜出它可能意味着什么,但不是最初。无论如何,看起来你能够以合理的方式解决问题,所以我想现在这是一个没有意义的问题。我承认内容有点“密集”。我试图避免一篇可能被“tldr”处理的冗长文章是的,
getContextualType()
仅在构造(反)序列化程序时可用,因为在实际(反)序列化过程中设置它对于大多数用例和大多数时间来说都是昂贵且不必要的(已构造(反)序列化程序被缓存)。此外,是的,您应该创建一个新的反序列化程序实例(就像你正在做的那样)因为否则会出现线程安全问题:反序列化程序应该是无状态的。因此我认为您找到了解决问题的合理方法。@StaxMan尽管我已经按照上述方式完成了我的工作,但我仍然想知道如何访问@JsonDeserializer#contentAs值……您可以从createcontext()方法的
ContextualDeserializer
BeanProperty
都应该在修改后具有类型