Гессон Deserialization с Kotlin, блок инициализатора не называется

Мой блок инициализации работает отлично, когда я создаю свой объект

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 и поддерживает значения параметров по умолчанию, так же как и 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