我在我的项目中使用 Jackson 和 Kotlin 绑定。我们有一个数据类,它有一个类型为Map<A, B>
的字段,名为"isRecommendation"。当 Jackson 序列化数据类时,生成的 JSON 字符串中会省略此字段。
重现相同行为的简单测试:
class FooKotlin {
@Test
fun testFoo() {
println(jacksonObjectMapper().writeValueAsString(Foo1(true)))
println(jacksonObjectMapper().writeValueAsString(Foo2(1)))
println(jacksonObjectMapper().writeValueAsString(Foo3("true")))
}
}
data class Foo1(val isFoo: Boolean)
data class Foo2(val isFoo: Int)
data class Foo3(val isFoo: String)
控制台打印:
{"foo":true}
{}
{}
当我反编译 Kotlin 字节码时,除了字段的类型之外,这三个类似乎具有几乎相同的内容。那么杰克逊这种行为的原因是什么呢?
正如@chrsblck所提到的,它与杰克逊模块-Kotlin 问题 #80 有关
在版本 2.10.1 上,它不可重现,尽管序列化的属性名称不同(不会删除"is"前缀(:
{"isFoo":true}
{"isFoo":1}
{"isFoo":"true"}
在早期版本中,可以使用JsonProperty
注释修复此问题:
data class Foo1(val isFoo: Boolean)
data class Foo2(@get:JsonProperty("foo") val isFoo: Int)
data class Foo3(@get:JsonProperty("foo") val isFoo: String)
{"foo":true}
{"foo":1}
{"foo":"true"}
从技术上讲,将非布尔属性命名为"isSomthing"是不正确的,并且违反了JavaBeans规范。杰克逊依赖于JavaBeans约定,因此它变得混乱。
如果你能避免这样的命名,我建议这样做。否则,从 Java 代码调用 Foo* 类时可能会遇到同样的问题。