用Kotlin进行Gson反序列化,不调用初始化块

当我创建我的对象时,我的初始化块工作得很好

class ObjectToDeserialize(var someString: String = "") : Serializable { init{ someString += " initialized" } } 

这条路:

 @Test fun createObject_checkIfInitialized() { assertEquals("someString initialized",ObjectToDeserialize("someString").someString) } 

但是,当我用Gson反序列化对象时,初始化块不会被执行:

 @Test fun deserializeObject_checkIfInitialized(){ val someJson: String = "{\"someString\":\"someString\" }" val jsonObject = Gson().fromJson(someJson, ObjectToDeserialize::class.java) assertEquals("someString initialized",jsonObject.someString) // Expected :someString initialized // Actual :someString } 

我认为,gson创建对象的方式不同于执行主构造函数。 是否有可能有类似的初始化块?


Gson旨在用于纯Java,不能正确解释Kotlin主构造函数。

如果有一个默认的无参构造函数,它会被调用(在你的情况下,有一个: someString默认值为""的主构造函数), 否则Gson根本不调用构造函数 。

然后Gson设置属性值(另外,它绕过Kotlin属性的实际设置者并直接设置字段,这有时会导致意外行为)。


作为替代方案,您可以使用jackson-module-kotlin ,它应该适用于您的情况(它了解Kotlin的主要构造函数,使用Kotlin setter,并且自2.8.x支持默认参数值)。

这个例子比较了jackson-module-kotlin和Kotson行为:

 class SomeClass(val id: Int = -1) { init { println("init $id") } } class SomeClassNoDefault(val id: Int) { init { println("init $id") } } fun main(args: Array<String>) { val mapper = jacksonObjectMapper() val gson = Gson() val idDefault = "{}" val id123 = "{\"id\": 123 }" println("jackson-module-kotlin, { }:") val o1 = mapper.readValue<SomeClass>(idDefault) println("after construction: ${o1.id}\n") println("jackson-module-kotlin, { \"id\" = 123 }:") val o2 = mapper.readValue<SomeClass>(id123) println("after construction: ${o2.id}\n") println("kotson, { }:") val o3 = gson.fromJson<SomeClass>(idDefault) println("after construction: ${o3.id}\n") println("kotson, { \"id\" = 123 }:") val o4 = gson.fromJson<SomeClass>(id123) println("after construction: ${o4.id}\n") println("---\n") println("jackson-module-kotlin, no default value, { \"id\" = 123 }:") val o5 = mapper.readValue<SomeClassNoDefault>(id123) println("after construction: ${o5.id}\n") println("kotson, no default value, { \"id\" = 123 }:") val o6 = gson.fromJson<SomeClassNoDefault>(id123) println("after construction: ${o6.id}\n") } 

输出是

 jackson-module-kotlin, { }: init -1 after construction: -1 jackson-module-kotlin, { "id" = 123 }: init 123 after construction: 123 kotson, { }: init -1 after construction: -1 kotson, { "id" = 123 }: init -1 after construction: 123 --- jackson-module-kotlin, no default value, { "id" = 123 }: init 123 after construction: 123 kotson, no default value, { "id" = 123 }: after construction: 123