2016-10-10 49 views
4

我的初始化塊是工作完全正常,當我創建我的對象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正在創建對象與通過執行主構造函數不同的方式。儘管如此,可能有類似初始化塊的東西嗎?


回答

9

Gson旨在用於純Java,並且不能正確解釋Kotlin主構造函數。

如果有一個默認的無參數的構造函數,它被稱爲(在你的情況下,有一個:與someString默認值""主構造),otherwise Gson calls no constructor at all

然後Gson設置屬性值(也繞過Kotlin屬性的實際設置者並直接設置字段,有時會導致意外行爲)。


作爲替代方案,你可以使用jackson-module-kotlin,它應該在你的情況下工作良好(它理解科特林主要構造,使用科特林制定者和支持默認參數值,以及因爲2.8.x)。

本實施例比較傑克遜模塊-科特林和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