在XPLPC项目中使用GSON和泛型与Kotlin转换为自定义类

v64noz0r  于 2022-11-06  发布在  Kotlin
关注(0)|答案(1)|浏览(167)

我有一个问题,看起来很简单,但我做错了什么。
如何在我的项目XPLPC中使用GSON和Kotlin从一个带有物化的泛型类进行转换?
错误在这里:https://github.com/xplpc/xplpc/actions/runs/3395808126/jobs/5646151499#step:9:503

com.xplpc.library.TodoTest > singleItem[test(AVD) - 12] FAILED 
    java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.xplpc.library.TodoTest$Todo
    at com.xplpc.library.TodoTest.singleItem(TodoTest.kt:44)

它不理解我想要转换为Todo类而不是LinkedTreeMap。
代码如下:https://github.com/xplpc/xplpc/blob/main/kotlin/lib/library/src/main/java/com/xplpc/serializer/JsonSerializer.kt#L66-L79
代码由以下函数调用:https://github.com/xplpc/xplpc/blob/main/kotlin/lib/library/src/main/java/com/xplpc/client/RemoteClient.kt#L14-L27
基本代码是:

// Part 1
object RemoteClient {
    inline fun <reified T> call(request: Request, defValue: T? = null): T? {
        try {
            val data = PlatformProxy.call(request.data)
            println(data)
            return XPLPC.config.serializer.decodeFunctionReturnValue<T>(data)
        } catch (e: Exception) {
            Log.e(
                Constants.LOG_GROUP,
                "[RemoteClient : call] Error when try to decode return value: ${e.message}"
            )
        }

        return defValue
    }

    inline fun <reified T> callAsync(request: Request, defValue: T? = null): Deferred<T?> {
        return CoroutineScope(Dispatchers.IO).async {
            return@async call<T>(request, defValue)
        }
    }
}

// Part 2
override fun <T> decodeFunctionReturnValue(data: String): T? {
    try {
        val type = object : TypeToken<JsonFunctionReturnValueData<T>>() {}.type
        val gson = createGson()
        return gson.fromJson<JsonFunctionReturnValueData<T>>(data, type).r
    } catch (e: Exception) {
        Log.e(
            Constants.LOG_GROUP,
            "[JsonSerializer : decodeFunctionReturnValue] Error when parse json: ${e.message}"
        )
    }

    return null
}
wi3ka0sx

wi3ka0sx1#

问题是对于decodeFunctionReturnValue函数,类型参数T不是reified。因此在运行时,您创建的TypeToken实际上是TypeToken<JsonFunctionReturnValueData<**Object**>>。在反序列化Object时,Gson基于JSON数据标准对象创建JSON对象,该对象是Java Map(Gson的内部实现是LinkedTreeMap)。
因此,如果可能的话,解决方案是使类型参数T也在这里reified。如果不可能,也许该类型可以作为单独的TypeToken参数传递给函数。
旁注:当创建捕获类型变量的TypeToken时,Gson应该抛出异常的是already suggested(这将通知您代码的问题)。但是,由于向后兼容性问题,这还没有实现。

相关问题