如何让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全局生效:
- 自定义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 } } } }
- 注册到Gson并配置给Retrofit
val gson = GsonBuilder() .registerTypeAdapterFactory(NullOnEmptyTypeAdapterFactory()) .create() val retrofit = Retrofit.Builder() .baseUrl(你的服务地址) .addConverterFactory(GsonConverterFactory.create(gson)) // 其他配置 .build()
配置完成后,所有反序列化后全字段为空的对象都会自动返回null,你原有代码中的responseData == null判断就可以正常触发。
内容的提问来源于stack exchange,提问作者Cofyka
相关产品推荐
相关产品推荐

