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

问题描述 投票:0回答:1

我有一个看似简单的问题,但我犯了一些错误。

我如何在名为 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
}
java android json kotlin gson
1个回答
0
投票

问题是,对于您的

decodeFunctionReturnValue
函数,类型参数
T
不是
reified
。因此,在运行时,您创建的
TypeToken
实际上是
TypeToken<JsonFunctionReturnValueData<Object>>
。反序列化时
Object
,Gson基于JSON数据标准对象创建,对于一个JSON对象来说,它是一个Java
Map
(Gson的内部实现是
LinkedTreeMap
)。

因此,如果可能的话,解决方案是将类型参数

T
也设置为
reified
。如果这是不可能的,也许可以将该类型作为单独的
TypeToken
参数传递给函数。


未来的 Gson 版本(> 2.10.1)将在

TypeToken
捕获类型变量时引发异常,因此允许您更早地识别此类问题。 故障排除指南包含其他信息和解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.