2017-08-26 45 views
2

我正在編程一個kotlin websocket並想發送轉換爲json與gson的dtos。所以我寫了一種包裝dto,其中包含真正的dto和一些關於dto的附加信息,如其類型。這是我的包裝DTO使用gson序列化和返回不適用於泛型類型

class WrapperDto <T : AbstractDto> { 
    var type = "" 
    var action = "" 
    var dto : T = AbstractDto() as T 
} 

,這是DTOS,它可以包含一個:

class Person : AbstractDto() { 
    var firstName = "" 
    var familyName = "" 
} 

這裏測試的原因,我嘗試tansform它JSON,然後再返回:

val wrapperDto2 = WrapperDto<Person>() 
    wrapperDto2.type = Person::class.simpleName!!; 
    wrapperDto2.action = "add" 
    val person = Person() 
    person.firstName = "Richard" 
    person.familyName = "Lederer" 
    wrapperDto2.dto = person; 

    val gson1 = Gson() 
    val toJson = gson1.toJson(wrapperDto2) 
    println("to json: " + toJson) 
    val fromJson = gson1.fromJson(toJson, wrapperDto2::class.java) 
    println("from json: " + fromJson) 

最後一個println永遠不會被調用,我得到以下錯誤信息:

java.lang.IllegalArgumentException: Can not set at.richardlederer.contactmanager.dto.AbstractDto field at.richardlederer.contactmanager.dto.WrapperDto.dto to com.google.gson.internal.LinkedTreeMap 
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) 
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) 
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) 

我該如何解決這個問題?

回答

3

這是由於的generics。您需要使用TokenType來在運行時檢索類型信息。

val fromJson = gson1.fromJson<WrapperDto<Person>>(toJson, object: TypeToken<WrapperDto<Person>>() {}.type) 

您還可以創建一個擴展功能是這樣的:

inline fun <reified T> fromJson(json: String): T = Gson().fromJson<T>(json, object: TypeToken<T>() {}.type) 

所以,你可以調用fromJson這樣:

val fromJson = fromJson<WrapperDto<Person>>(toJson) 
//Or 
val fromJson: WrapperDto<Person> = fromJson(toJson) //Type inferred