2017-08-26 48 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