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

如何在Kotlin Android中为嵌套数据类自定义Retrofit转换器工厂

问题:Retrofit嵌套字段类型转换与方案选择

我的模型类为StudentResponse,现有自定义Retrofit Converter Factory代码如下:

class BaseConverterFactory private constructor() : Converter.Factory() {
    override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
        LogUtils.d("Hello type: " + type)
        if (type === String::class.java) {
            return Converter { value -> value.string() }
        } else if (type === Int::class.java) {
            return Converter { value -> Integer.valueOf(value.string()) }
        } else if (type === Double::class.java) {
            return Converter { value -> java.lang.Double.valueOf(value.string()) }
        } else if (type === Boolean::class.java) {
            return Converter { value -> java.lang.Boolean.valueOf(value.string()) }
        }
        return null
    }

    companion object {
        fun create(): BaseConverterFactory {
            return BaseConverterFactory()
        }
    }
}

对应的实体类代码:

data class StudentResponse(
    var aggregatedValues: List<Books>?,
)

data class Books(
    var bookValue: Double?, // 需要将接口返回的Double值(如34.11)取整为Int存入该字段
)

当前Converter仅能处理基础类型的直接转换,无法处理StudentResponse嵌套结构中Books类的bookValue字段类型转换需求。另外,针对全项目频繁出现的这类类型转换场景,选择Retrofit Converter Factory还是Gson反序列化方案更合适?


解答

一、实现嵌套字段的类型转换

方案1:基于Gson自定义TypeAdapter

这是处理嵌套字段转换更直接的方式,针对特定字段或类定制反序列化规则:

  1. 为Books类编写自定义TypeAdapter:
class BooksTypeAdapter : TypeAdapter<Books>() {
    override fun write(out: JsonWriter, value: Books?) {
        // 序列化逻辑按需实现,此处仅处理反序列化
        out.beginObject()
        value?.bookValue?.let {
            out.name("bookValue").value(it.toInt())
        } ?: out.name("bookValue").nullValue()
        out.endObject()
    }

    override fun read(`in`: JsonReader): Books {
        var bookValue: Double? = null
        `in`.beginObject()
        while (`in`.hasNext()) {
            when (`in`.nextName()) {
                "bookValue" -> {
                    // 读取Double值后取整,再转为Double类型赋值(若字段可改为Int则直接转Int)
                    val doubleValue = `in`.nextDouble()
                    bookValue = doubleValue.toInt().toDouble()
                }
                else -> `in`.skipValue() // 跳过其他未处理字段
            }
        }
        `in`.endObject()
        return Books(bookValue)
    }
}
  1. 在Gson实例中注册适配器并配置到Retrofit:
val gson = GsonBuilder()
    .registerTypeAdapter(Books::class.java, BooksTypeAdapter())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()

方案2:扩展Retrofit Converter Factory

若坚持使用自定义Converter Factory,需结合Gson解析复杂对象,而非仅处理基础类型:

class CustomConverterFactory private constructor(private val gson: Gson) : Converter.Factory() {
    override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *> {
        val delegate = gson.getAdapter(TypeToken.get(type)) as TypeAdapter<Any>
        return Converter { body ->
            val json = body.string()
            val jsonElement = JsonParser.parseString(json)
            // 针对StudentResponse的嵌套字段做修改
            if (type === StudentResponse::class.java) {
                jsonElement.asJsonObject.getAsJsonArray("aggregatedValues")?.forEach { bookJson ->
                    val bookObj = bookJson.asJsonObject
                    if (bookObj.has("bookValue")) {
                        val doubleValue = bookObj.get("bookValue").asDouble
                        bookObj.addProperty("bookValue", doubleValue.toInt().toDouble())
                    }
                }
            }
            delegate.fromJson(jsonElement.toString())
        }
    }

    companion object {
        fun create(): CustomConverterFactory {
            val gson = GsonBuilder().create()
            return CustomConverterFactory(gson)
        }
    }
}

这种方式需手动遍历JSON结构,代码复杂度高,仅适合全局少量规则的场景。

二、方案对比与选择

方案优势劣势适用场景
Gson TypeAdapter1. 针对特定类/字段定制规则,精准度高
2. 代码模块化,易维护
3. 性能优于全局Converter
需为每个转换类编写适配器,多场景下代码量稍大项目中存在多个分散的字段/类转换需求
Retrofit Converter Factory1. 可全局统一处理所有请求响应
2. 无需修改实体类结构(部分场景)
1. 处理嵌套结构时需手动解析JSON,代码繁琐易出错
2. 全局规则灵活性低
单一全局转换规则的场景

结论:针对全项目频繁出现的类型转换需求,优先选择Gson自定义TypeAdapter方案。它更符合单一职责原则,代码可维护性更高,且能精准处理不同类的不同转换规则,避免全局Converter带来的复杂度。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:11:01