为什么@JsonIgnore注释在反序列化数据期间不起作用?



我有一个数据https://gist.githubusercontent.com/iva-nova-e-katerina/fc1067e971c71a73a0b525a21b336694/raw/954477261bb5ac2f52cee07a8bc45a2a27de1a8c/data2.json具有七个CheckResultItem元素的列表。我试着用这种方式解析它们:

import com.fasterxml.jackson.module.kotlin.readValue
...
val res = restHelper.objectMapper.readValue<List<CheckResultItem>>(text) 

这给了我以下错误:

com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.fmetric.validation.api.Brick] value failed for JSON property upperLevelBricks due to missing (therefore NULL) value for creator parameter upperLevelBricks which is a non-nullable type
at [Source: (StringReader); line: 1, column: 714] (through reference chain: java.util.ArrayList[0]->com.fmetric.validation.api.checking.CheckResultItem["brick"]->com.fmetric.validation.api.Brick["upperLevelBricks"])
at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:116)

数据类中有@JsonIgnore注释

data class Brick(
val id: UUID?,
val name: String,
val type: BrickType,
val propertyValues: List<ProjectBrickPropertyValue<*>>,
@JsonIgnore
val upperLevelBricks: ArrayList<Brick>,
val downLevelBricks: ArrayList<Brick>,    
var drawingDetails: List<BrickDrawingDetails>?
) {

但它似乎不起作用。你能解释一下怎么了吗?

UPD:我也尝试过@JsonIgnoreProperties({"upperLevelBricks"})类注释,但它不起作用。我的解决方案是设置一个默认值

val upperLevelBricks: ArrayList<Brick> = arrayListOf(),

但我认为注释应该起作用!

实际上,它是有效的,但不是你想的那样。在反序列化过程中,@JsonIgnore会忽略JSON中的尊重字段,就像它不存在一样(但在这种情况下,它没有意义,因为它最初在JSON中不存在(。

在Java中,Jackson只会为不存在的字段实例化具有null值的类(因为Java中的所有对象类型都是可为null的,这意味着它们允许将值设置为null(。但在Kotlin中,一个属性应该显式标记为可为null(val upperLevelBricks: List<Brick>?(或具有默认值(val upperLevelBricks: List<Brick> = emptyList()(,这样Jackson就可以在这种情况下创建一个类实例。

请注意,如果此字段存在于JSON中,但显式设置为null:,则使用属性默认值的方法将不起作用(除非您另外用@JsonIgnore标记它(

{
...
"upperLevelBricks": null,
...
}

无论如何,如果您不想更改Brick类的API,则只有在Jackson反序列化期间创建该字段时(并且只有在JSON中不存在/null时(,才可以通过自定义反序列化器为该字段提供默认值

object EmptyListAsDefault : JsonDeserializer<List<Brick>>() {
override fun deserialize(jsonParser: JsonParser, context: DeserializationContext): List<Brick> =
jsonParser.codec.readValue(
jsonParser,
context.typeFactory.constructCollectionType(List::class.java, Brick::class.java)
)
override fun getNullValue(context: DeserializationContext): List<Brick> = emptyList()
}
data class Brick(
//...
@JsonDeserialize(using = EmptyListAsDefault::class)
val upperLevelBricks: List<Brick>,
//...
)

最新更新