当我反序列化到我的类中时,对于一些字段,我希望能够区分值是缺失还是空。例如,{"id": 5, "name": null}
应该被认为不同于{"id": 5}
。
我遇到过kotlinx.serialisation和Rust's serde的解决方案,但到目前为止,我还在努力在Jackson实现这一点。
我将使用这个类作为示例:
data class ResponseJson(
val id: Int,
@JsonDeserialize(using = OptionalPropertyDeserializer::class)
val name: OptionalProperty<String?>
)
OptionalProperty字段的定义:
sealed class OptionalProperty<out T> {
object Absent : OptionalProperty<Nothing>()
data class Present<T>(val value: T?) : OptionalProperty<T>()
}
我编写了一个自定义反序列化器:
class OptionalPropertyDeserializer :
StdDeserializer<OptionalProperty<*>>(OptionalProperty::class.java),
ContextualDeserializer
{
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): OptionalProperty<*> {
println(p.readValueAs(ctxt.contextualType.rawClass))
return OptionalProperty.Present(p.readValueAs(ctxt.contextualType.rawClass))
}
override fun getNullValue(ctxt: DeserializationContext?) = OptionalProperty.Present(null)
override fun getAbsentValue(ctxt: DeserializationContext?) = OptionalProperty.Absent
override fun createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer<*> {
println(property.type.containedType(0))
return ctxt.findContextualValueDeserializer(property.type.containedType(0), property)
}
}
最后,我的ObjectMapper设置:
val messageMapper: ObjectMapper = jacksonObjectMapper()
.disable(ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
.disable(ACCEPT_FLOAT_AS_INT)
.enable(FAIL_ON_NULL_FOR_PRIMITIVES)
.enable(FAIL_ON_NUMBERS_FOR_ENUMS)
.setSerializationInclusion(NON_EMPTY)
.disable(WRITE_DATES_AS_TIMESTAMPS)
现在,我尝试反序列化一些JSON:
@Test
fun deserialiseOptionalProperty() {
assertEquals(
ResponseJson(5, OptionalProperty.Present("fred")),
messageMapper.readValue(
//language=JSON
"""
{
"id": 5,
"name": "fred"
}
""".trimIndent()
)
)
}
出现以下异常:
com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `serialisation_experiments.JacksonTests$ResponseJson`, problem: argument type mismatch
at [Source: (String)"{
"id": 5,
"name": "fred"
}"; line: 4, column: 1]
这里的“参数类型不匹配”是什么意思?我假设我对自定义反序列化器做了一些不正确的事情,但是正确的方法是什么呢?
1条答案
按热度按时间dm7nw8vv1#
我使用了
OptionalProperty
类的一个实现,它有一个字段来保存值,还有一个标志来指示值是否被设置。每当值被更改时,使用自定义的setter,该标志将被设置为true。有了这样一个类和默认的jacksonObjectMapper()
,我就能够获得所有场景的反序列化工作名称指定,name null和name missing.下面是我最终得到的类:可选属性:
回应:
可选属性反序列化程序:
测试:
包含主类和测试类的完整项目可以在github中找到