You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Retrofit加载钱包遇JSON格式异常,需设临时值规避错误

解决Retrofit解析Wallet字段类型不匹配的异常问题

你的问题核心是:接口返回的wallet字段可能是对象、空数组或空字符串,但你的实体类定义的是Wallet对象类型,导致Retrofit解析时直接抛出java.lang.IllegalStateException——因为解析器期望对象,却收到了数组/字符串。你之前的代码没用是因为异常发生在Retrofit解析响应的阶段,还没走到你判断data.wallet == null的逻辑就报错了。

下面提供两种可行的解决方案:


方案一:自定义Gson TypeAdapter(推荐)

给Wallet类自定义解析适配器,在解析时捕获类型不匹配的异常,直接返回默认值。

步骤1:编写TypeAdapter

class WalletTypeAdapter : TypeAdapter<Wallet>() {
    override fun write(out: JsonWriter, value: Wallet?) {
        // 序列化逻辑(如果不需要自定义,用默认Gson序列化即可)
        Gson().toJson(value, Wallet::class.java, out)
    }

    override fun read(`in`: JsonReader): Wallet {
        return try {
            // 尝试正常解析为Wallet对象
            Gson().fromJson(`in`, Wallet::class.java)
        } catch (e: JsonSyntaxException) {
            // 解析失败(说明是数组/空字符串等非对象类型),跳过错误值并返回默认Wallet
            `in`.skipValue()
            Wallet(subscriberId = 0, currentBalance = "0.00")
        }
    }
}

步骤2:注册Adapter到Gson并配置Retrofit

创建Gson实例时注册这个适配器,再传给Retrofit的ConverterFactory:

val customGson = GsonBuilder()
    .registerTypeAdapter(Wallet::class.java, WalletTypeAdapter())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl(YOUR_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(customGson))
    // 其他配置(如OkHttpClient)
    .build()

这样,当接口返回wallet为数组或空字符串时,适配器会自动处理并返回默认的Wallet对象,不会抛出解析异常,后续你的业务逻辑可以正常执行。


方案二:将Wallet字段改为JsonElement手动解析

修改实体类的wallet字段类型为JsonElement,在解析后手动判断类型并处理:

步骤1:修改响应实体类

data class WalletResponse(
    val wallet: JsonElement?
)

data class Wallet(
    val subscriberId: Long,
    val currentBalance: String
)

步骤2:在业务逻辑中手动解析

.suspendOnSuccess {
    val targetWallet = when {
        // 处理null或空值
        data.wallet == null || data.wallet.isJsonNull -> Wallet(0, "0.00")
        // 正常对象类型,解析为Wallet
        data.wallet.isJsonObject -> {
            val jsonObj = data.wallet.asJsonObject
            Wallet(
                subscriberId = jsonObj.get("subscriberId").asLong,
                currentBalance = jsonObj.get("currentBalance").asString
            )
        }
        // 数组或其他非法类型,返回默认值
        else -> Wallet(0, "0.00")
    }
    // 这里可以根据需要转换为业务模型,或者直接使用targetWallet
    emit(targetWallet)
}

这种方式不需要自定义适配器,但需要手动处理解析逻辑,适合快速临时解决问题。

内容的提问来源于stack exchange,提问作者denver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 07:19:57