我想我在这里遗漏了一些明显的东西,但是我似乎不能使用Spring/Kotlin/Jackson反序列化一个简单的泛型容器。
所讨论的数据类型非常简单:
@JsonDeserialize(using = PatchableDeserializer::class)
sealed class Patchable<T> {
class Undefined<T>: Patchable<T>()
class Null<T>: Patchable<T>()
data class Present<T>(val content: T): Patchable<T>()
// …
}
解串器扩展了ReferenceTypeDeserializer
,就像jdk 8模块的OptionalDeserializer
一样。
class PatchableDeserializer(javaType: JavaType, vi: ValueInstantiator, typeDeser: TypeDeserializer, deser: JsonDeserializer<*> ):
ReferenceTypeDeserializer<Patchable<*>>(javaType, vi, typeDeser, deser) {
// …
}
我假设Jackson会在这里填写PatchableDeserializer
的构造函数参数,但是,情况似乎并非如此:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'my.namespace.PatchableDeserializer': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.JavaType' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我会假设Jackson提供了javaType
的值,因为我在编译时无法知道它。
下面是我用来测试的代码,它会生成上面的异常:
@RunWith(SpringRunner::class)
@JsonTest
class PatchableTest {
@Autowired
lateinit var objectMapper: ObjectMapper
@Test
fun patchableDeserialisesStringValue() {
val value: Patchable<String> = objectMapper.readValue("\"null\"", object: TypeReference<Patchable<String>>() {})
assertTrue(value.isPresent())
assertEquals("null", value.unsafeGetValue())
}
}
我错过了什么?而且,我在网上找了很长时间才找到一些关于如何反序列化泛型类型的信息,所以如果有人有关于如何为泛型类型编写自定义反序列化器的指针,我将非常感激。
2条答案
按热度按时间pbpqsu0x1#
泛型容器的还原序列化(延伸
com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer
)无法以这种方式登录。您需要使用覆写
findReferenceDeserializer
方法来注册com.fasterxml.jackson.databind.deser.Deserializers
的自订实作。这个方法会呼叫,以寻找指涉型别之值的还原序列化程式。您还需要添加
com.fasterxml.jackson.databind.type.TypeModifier
,它将把“泛型容器”类型修改为com.fasterxml.jackson.databind.type.ReferenceType
,这样您的自定义ReferenceTypeDeserializer
将被调用。最简单的方法是注册一个自定义的
com.fasterxml.jackson.databind.Module
,它将addDeserializers
和addTypeModifier
。一个很好的例子是Jdk8Module
,它为java.util.Optional
和它的朋友做所有的工作。为自定义泛型容器
MyRef
注册反序列化程序的完整示例:MyRefDeserializer
。这只是一个例子。被覆盖方法的具体实现(以及需要覆盖哪些方法)将取决于您的要求。Deserializers
接口的实现:TypeModifier
的一种实现,它允许Jackson理解MyRef
是一种ReferenceType
类型:最后是
Module
,它将注册反序列化器和类型修饰符:然后,您需要使用
ObjectMapper
注册此模块。例如:如果您使用Sping Boot ,则只需将模块公开为
@Bean
,它将自动注册为默认的ObjectMapper
。vddsk6oq2#
我最终为我的反序列化器实现了一个不同的接口。
这可以正常工作,但是Jackson需要解析器中的上下文信息来使其工作,也就是说,上面的测试代码不起作用。但是,如果显式指定要反序列化到的DTO,并且该DTO具有正确的类型注解,它就可以工作。