我想我这里缺少明显的东西,但是我似乎无法使用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
,就像jdk8模块的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())
}
}
我想念什么?另外,我在网上很难找到有关如何反序列化泛型类型的信息,因此,如果有人有指针如何为泛型类型编写自定义反序列化器,我将非常感激。
答案 0 :(得分:0)
我最终为反序列化器实现了一个不同的接口。
class PatchableDeserializer(private val valueType: Class<*>?): JsonDeserializer<Patchable<*>>(), ContextualDeserializer {
override fun createContextual(ctxt: DeserializationContext?, property: BeanProperty?): JsonDeserializer<*> {
val wrapperType = property?.type
val rawClass = wrapperType?.containedType(0)?.rawClass
return PatchableDeserializer(rawClass)
}
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Patchable<*> =
Patchable.of(p!!.readValueAs(valueType))
override fun getNullValue(ctxt: DeserializationContext?): Patchable<Any> =
if (ctxt?.parser?.currentToken == JsonToken.VALUE_NULL)
Patchable.ofNull()
else
Patchable.undefined()
}
这可以按预期工作,但是Jackson需要解析器中的上下文信息以使其起作用,即上述测试代码不起作用。但是,如果您明确指定要反序列化的DTO(如果它具有正确的类型注释),它将起作用。