使用Gson解析Kotlin stdlib.Result类型时访问值抛出ClassCastException
问题原因
- 核心问题是Kotlin标准库的
Result<T>属于值类(value class),Gson作为Java生态的序列化框架,对Kotlin特有的值类支持不完善,无法将TypeToken<Result<SomeObject>>携带的泛型信息正确传递到Result内部持有的value字段上,因此会默认将JSON对象解析为LinkedTreeMap类型存储在Result内部。 - 调试时能看到完整值是因为调试器仅读取Result内部的原始存储值,不会触发类型转换逻辑;只有当你调用
onSuccess、getOrNull等需要返回SomeObject类型的方法时,才会执行隐式的强转操作,此时就会抛出类型不匹配异常。
解决方案
方案1(更简单,推荐):先解析目标类型再手动包装为Result
跳过直接解析Result的步骤,先把JSON解析为实际业务类型SomeObject,再用Kotlin标准库方法手动包装为Result,完全规避Gson对Result类型的适配问题:
val result = runCatching { gson.fromJson(jsonString, SomeObject::class.java) } // 原有逻辑完全不用改 assertTrue(result.isSuccess) result.onSuccess { println(it) }
如果要兼容JSON解析成功但业务层面需要返回Failure的场景,也可以自行判断后调用Result.success()或Result.failure()手动封装。
方案2:自定义Result类型的Gson TypeAdapter
如果确实需要直接反序列化为Result<T>类型,可以自定义TypeAdapter实现适配,手动处理泛型参数的解析逻辑:
class ResultTypeAdapter<T>(private val dataType: Type) : TypeAdapter<Result<T>>() { override fun write(writer: JsonWriter, value: Result<T>?) { // 按需实现序列化逻辑 } override fun read(reader: JsonReader): Result<T> { return try { val value = Gson().fromJson<T>(reader, dataType) Result.success(value) } catch (e: Exception) { Result.failure(e) } } } // 注册Adapter后使用 val gson = GsonBuilder() .registerTypeAdapterFactory { gson, type -> if (type.rawType != Result::class.java) return@registerTypeAdapterFactory null val actualType = (type.type as ParameterizedType).actualTypeArguments[0] ResultTypeAdapter<Any>(actualType) as TypeAdapter<*> } .create()
内容的提问来源于stack exchange,提问作者zhaider
相关产品推荐
相关产品推荐

