如何在转换为实体类前修改Retrofit JSON响应的根节点?
优化方案:单解析流程实现
完全可以通过一次解析完成需求,核心思路是直接使用Gson的JsonReader流式解析响应体,跳过无关字段,直接读取result并转换为T,同时捕获错误信息。这种方式避免了中间的字符串转换和二次解析,性能更优。
步骤1:替换GsonResponseBodyConverter为优化版本
internal class OptimizedGsonResponseBodyConverter<T>( private val gson: Gson, private val adapter: TypeAdapter<T> ) : Converter<ResponseBody, T> { @Throws(IOException::class) override fun convert(value: ResponseBody): T { value.use { responseBody -> val jsonReader = gson.newJsonReader(responseBody.charStream()) jsonReader.beginObject() var isDone = false var result: T? = null var errorMsg: String? = null while (jsonReader.hasNext()) { when (jsonReader.nextName()) { "done" -> isDone = jsonReader.nextBoolean() "response" -> { if (isDone) { // 仅在成功时解析response中的result jsonReader.beginObject() while (jsonReader.hasNext()) { if (jsonReader.nextName() == "result") { result = adapter.read(jsonReader) } else { jsonReader.skipValue() // 跳过response中的其他字段 } } jsonReader.endObject() } else { jsonReader.skipValue() // 失败时跳过response字段 } } "error" -> { if (!isDone) { // 仅在失败时解析error中的message jsonReader.beginObject() while (jsonReader.hasNext()) { if (jsonReader.nextName() == "message") { errorMsg = jsonReader.nextString() } else { jsonReader.skipValue() // 跳过error中的其他字段 } } jsonReader.endObject() } else { jsonReader.skipValue() // 成功时跳过error字段 } } else -> jsonReader.skipValue() // 跳过其他未知字段 } } jsonReader.endObject() return result ?: throw ProxyExecutionException(errorMsg ?: "响应解析失败:无有效结果或错误信息") } } }
步骤2:更新ProxyGsonConverterFactory返回优化后的转换器
只需修改responseBodyConverter方法,返回OptimizedGsonResponseBodyConverter即可:
override fun responseBodyConverter( type: Type, annotations: Array<Annotation>, retrofit: Retrofit ): Converter<ResponseBody, *> { val adapter = gson.getAdapter(TypeToken.get(type)) return OptimizedGsonResponseBodyConverter(gson, adapter) }
方案优势
- 单次解析:直接流式读取响应体,无需将整个JSON转为
JSONObject或中间字符串,彻底消除二次解析的性能损耗。 - 灵活兼容:无需修改Retrofit接口的返回类型,保持原有
T类型的定义。 - 错误处理:准确捕获错误场景中的
message字段,抛出自定义异常。
内容的提问来源于stack exchange,提问作者Viewed
相关产品推荐
相关产品推荐

