我有一个数据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>,
//...
)