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

如何让Retrofit在返回类型不匹配时将响应反序列化为null对象

核心原因

你遇到的问题本质是Gson默认反序列化策略导致的:只要输入是合法JSON对象,即使和目标类没有任何匹配字段,Gson也会实例化目标类,所有可空字段赋值为null,不会抛出异常也不会返回null。你的错误返回JSON只有error字段,和DefaultResponseResult的三个字段完全不匹配,所以就得到了全空属性的实例。


方案1:快速适配,在请求封装层加校验

改动最小,不需要修改全局配置,直接在现有fetch方法中加判断即可:

override fun onResponse(call: Call<T?>, response: Response<T?>) {
    val responseData = response.body()
    var errorLog: ErrorLog? = null

    // 校验DefaultResponseResult是否全字段为空
    if (responseData is DefaultResponseResult) {
        val isAllFieldNull = responseData.success == null 
                && responseData.action == null 
                && responseData.res == null
        if (isAllFieldNull) {
            // 手动读取原始响应解析错误信息
            val rawJson = response.raw().body?.string() ?: ""
            // 注意:你当前ErrorLog定义和实际返回不匹配,实际返回的error是字符串不是ErrorLogBody对象,需要修改ErrorLog的error字段类型为String才能正常解析
            errorLog = try {
                gson.fromJson(rawJson, ErrorLog::class.java)
            } catch (e: Exception) {
                null
            }
            // 按照需求走错误分支
            completion(Failure(APIError(internalError = errorLog?.error ?: "Response type mismatch")))
            return
        }
    }

    // 原有逻辑不变
    if (responseData == null) {
        completion(Failure(APIError(internalError = "Unknown")))
        return
    }

    printLogs(responseData.toString())
    completion(Success(responseData))
}

方案2:全局配置反序列化规则,全空对象自动返回null

如果所有接口都需要遵循「类型不匹配返回null」的规则,可以自定义Gson的TypeAdapterFactory全局生效:

  1. 自定义TypeAdapterFactory
class NullOnEmptyTypeAdapterFactory : TypeAdapterFactory {
    override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
        val delegateAdapter = gson.getDelegateAdapter(this, type)
        return object : TypeAdapter<T>() {
            override fun write(out: JsonWriter, value: T?) {
                delegateAdapter.write(out, value)
            }

            override fun read(`in`: JsonReader): T? {
                val jsonElement = JsonParser.parseReader(`in`)
                val obj = delegateAdapter.fromJsonTree(jsonElement) ?: return null
                // 反射检查所有成员字段是否全为null
                var allFieldNull = true
                for (field in obj.javaClass.declaredFields) {
                    // 过滤掉序列化无关的合成字段
                    if (field.isSynthetic) continue
                    field.isAccessible = true
                    if (field.get(obj) != null) {
                        allFieldNull = false
                        break
                    }
                }
                return if (allFieldNull) null else obj
            }
        }
    }
}
  1. 注册到Gson并配置给Retrofit
val gson = GsonBuilder()
    .registerTypeAdapterFactory(NullOnEmptyTypeAdapterFactory())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl(你的服务地址)
    .addConverterFactory(GsonConverterFactory.create(gson))
    // 其他配置
    .build()

配置完成后,所有反序列化后全字段为空的对象都会自动返回null,你原有代码中的responseData == null判断就可以正常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 02:09:02