杰克逊结合@JsonIdentityInfo 和@JsonTypeInfo 抛出 InvalidTypeIdException
Jackson combining @JsonIdentityInfo and @JsonTypeInfo throws InvalidTypeIdException
目前,当我合并 @JsonIdentityInfo
和 @JsonTypeInfo
时,我遇到了 Jackson 的问题。下面的 Kotlin 代码在最后一行抛出异常。它按预期将 dog1AndDog1Json
实例序列化为 Json,但随后在将其反序列化回实例时抛出异常。
package some.test
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.databind.ObjectMapper
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonSubTypes(JsonSubTypes.Type(value = Dog::class), JsonSubTypes.Type(value = Cat::class))
interface Animal {
val name: String
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
data class Dog(@JsonProperty("name") override val name: String) : Animal
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
data class Cat(@JsonProperty("name") override val name: String) : Animal
data class TwoAnimals(@JsonProperty("animal1") val animal1: Animal, @JsonProperty("animal2") val animal2: Animal)
fun main() {
val om = ObjectMapper();
val dog1 = Dog("Dog1")
val dog2 = Dog("Dog2")
val cat1 = Cat("Cat1")
val dog1AndDog2 = TwoAnimals(dog1, dog2)
val dog1AndDog2Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndDog2)
assert(dog1AndDog2 === om.readValue(dog1AndDog2Json, TwoAnimals::class.java)) // OK
val dog1AndCat1 = TwoAnimals(dog1, cat1)
val dog1AndCat2Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndCat1)
assert(dog1AndCat1 === om.readValue(dog1AndCat2Json, TwoAnimals::class.java)) // OK
val dog1AndDog1 = TwoAnimals(dog1, dog1)
val dog1AndDog1Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndDog1)
println(dog1AndDog1Json)
assert(dog1AndDog1 === om.readValue(dog1AndDog1Json, TwoAnimals::class.java)) // DESERIALIZE FAILS
}
然后我 运行 主函数我得到以下输出:
{
"animal1" : {
"@class" : "some.test.Dog",
"@id" : 1,
"name" : "Dog1"
},
"animal2" : 1
}
紧随其后的是这个异常:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class some.test.Animal]: missing type id property '@class' (for POJO property 'animal2')
at [Source: (String)"{
"animal1" : {
"@class" : "some.test.Dog",
"@id" : 1,
"name" : "Dog1"
},
"animal2" : 1
}"; line: 7, column: 15] (through reference chain: some.test.TwoAnimals["animal2"])
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
<truncated rest of stacktrace>
Jackson 似乎希望 animal2
属性 处有一个 @class 属性 的对象找到正确的 class 类型反序列化。但它已被 @JsonIdentityInfo
注释替换为一个 id。为什么 Jackson 不通过该 id 查找对象,然后检查该实例的 @class 属性?
我不确定 Jackson 是否不支持这个用例,或者我做错了什么(我所希望的)。或者这可能是一个错误?
我设法通过以下方式让它工作:
- 正在从
Dog
和 Car
子 classes 中删除 @JsonIdentityInfo
注释
- 将
@JsonIdentityInfo
添加到 Animal
基础 class
目前,当我合并 @JsonIdentityInfo
和 @JsonTypeInfo
时,我遇到了 Jackson 的问题。下面的 Kotlin 代码在最后一行抛出异常。它按预期将 dog1AndDog1Json
实例序列化为 Json,但随后在将其反序列化回实例时抛出异常。
package some.test
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.databind.ObjectMapper
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonSubTypes(JsonSubTypes.Type(value = Dog::class), JsonSubTypes.Type(value = Cat::class))
interface Animal {
val name: String
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
data class Dog(@JsonProperty("name") override val name: String) : Animal
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
data class Cat(@JsonProperty("name") override val name: String) : Animal
data class TwoAnimals(@JsonProperty("animal1") val animal1: Animal, @JsonProperty("animal2") val animal2: Animal)
fun main() {
val om = ObjectMapper();
val dog1 = Dog("Dog1")
val dog2 = Dog("Dog2")
val cat1 = Cat("Cat1")
val dog1AndDog2 = TwoAnimals(dog1, dog2)
val dog1AndDog2Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndDog2)
assert(dog1AndDog2 === om.readValue(dog1AndDog2Json, TwoAnimals::class.java)) // OK
val dog1AndCat1 = TwoAnimals(dog1, cat1)
val dog1AndCat2Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndCat1)
assert(dog1AndCat1 === om.readValue(dog1AndCat2Json, TwoAnimals::class.java)) // OK
val dog1AndDog1 = TwoAnimals(dog1, dog1)
val dog1AndDog1Json = om.writerWithDefaultPrettyPrinter().writeValueAsString(dog1AndDog1)
println(dog1AndDog1Json)
assert(dog1AndDog1 === om.readValue(dog1AndDog1Json, TwoAnimals::class.java)) // DESERIALIZE FAILS
}
然后我 运行 主函数我得到以下输出:
{
"animal1" : {
"@class" : "some.test.Dog",
"@id" : 1,
"name" : "Dog1"
},
"animal2" : 1
}
紧随其后的是这个异常:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class some.test.Animal]: missing type id property '@class' (for POJO property 'animal2')
at [Source: (String)"{
"animal1" : {
"@class" : "some.test.Dog",
"@id" : 1,
"name" : "Dog1"
},
"animal2" : 1
}"; line: 7, column: 15] (through reference chain: some.test.TwoAnimals["animal2"])
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
<truncated rest of stacktrace>
Jackson 似乎希望 animal2
属性 处有一个 @class 属性 的对象找到正确的 class 类型反序列化。但它已被 @JsonIdentityInfo
注释替换为一个 id。为什么 Jackson 不通过该 id 查找对象,然后检查该实例的 @class 属性?
我不确定 Jackson 是否不支持这个用例,或者我做错了什么(我所希望的)。或者这可能是一个错误?
我设法通过以下方式让它工作:
- 正在从
Dog
和Car
子 classes 中删除 - 将
@JsonIdentityInfo
添加到Animal
基础 class
@JsonIdentityInfo
注释