使用gson序列化和返回不适用于泛型类型 [英] serializing with gson and back does not work with generic types

查看:485
本文介绍了使用gson序列化和返回不适用于泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个kotlin websocket,并且想用gson发送转换为json的dtos。所以我写了一种包装dto,其中包含真正的dto和一些关于dto的附加信息,如其类型。这是我的包装dto

i am programming a kotlin websocket and want to send dtos transformed to json with gson. so i wrote a kind of wrapper dto that contains the real dto and some additional information about the dto, like the type of it. this is my wrapper dto

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

,这是它可以包含的一个命令:

and this is one of the dtos that it can contain:

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

这里出于测试原因,我尝试将其转换为json并返回:

here for test reasons i try to tansform it to json and back again:

    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永远不会被调用,我得到以下错误消息:

the last println is never called and i get following error message:

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)

我该如何解决这个问题?

how can i solve this problem?

推荐答案

这是由于 type erasure 泛型的。您需要使用 TokenType 在运行时检索类型信息。

It is due to type erasure of generics. You need to use TokenType to retrieve the type information at runtime.

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

您也可以创建一个扩展函数,如下所示:

You may also create an extension function like this:

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

因此,您可以通过以下方式从 >

So, you can call fromJson this way:

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

这篇关于使用gson序列化和返回不适用于泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆