我有一个看似简单的问题,但我犯了一些错误。
我如何在名为 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。
基本上代码是:
// 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
}
问题是,对于您的
decodeFunctionReturnValue
函数,类型参数 T
不是 reified
。因此,在运行时,您创建的 TypeToken
实际上是 TypeToken<JsonFunctionReturnValueData<Object>>
。反序列化时Object
,Gson基于JSON数据标准对象创建,对于一个JSON对象来说,它是一个JavaMap
(Gson的内部实现是LinkedTreeMap
)。
因此,如果可能的话,解决方案是将类型参数
T
也设置为 reified
。如果这是不可能的,也许可以将该类型作为单独的 TypeToken
参数传递给函数。
未来的 Gson 版本(> 2.10.1)将在
TypeToken
捕获类型变量时引发异常,因此允许您更早地识别此类问题。 故障排除指南包含其他信息和解决方法。