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

Android Kotlin中基于Retrofit+Dagger2实现通用TypeAdapterFactory与TypeAdapter

通用Gson TypeAdapter解决方案(兼容对象/数组、Double转Int)

针对你提出的两个核心场景,以下是基于TypeAdapter和TypeAdapterFactory的通用实现方案,完全符合你不使用JSONDeserializer的要求,适配MVVM+Retrofit+Dagger2架构:


场景1:同一键(含嵌套)兼容JSONObject/JSONArray

通过自定义注解标记需要兼容的字段,配合Factory实现自动识别处理:

1. 定义标记注解

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class SingleOrList

2. 实现通用TypeAdapterFactory

import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import java.lang.reflect.ParameterizedType
import java.util.Collections

class SingleOrListTypeAdapterFactory : TypeAdapterFactory {
    override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
        val rawType = type.rawType as Class<T>
        // 仅处理List类型且带有SingleOrList注解的字段
        if (!List::class.java.isAssignableFrom(rawType)) return null

        // 获取List的泛型元素类型
        val elementType = (type.type as? ParameterizedType)?.actualTypeArguments?.get(0) ?: Any::class.java
        val elementAdapter = gson.getAdapter(TypeToken.get(elementType))

        return object : TypeAdapter<T>() {
            override fun write(out: JsonWriter, value: T) {
                // 写入时直接使用元素适配器,支持单个元素或列表
                val list = value as List<*>
                if (list.size == 1) elementAdapter.write(out, list[0])
                else gson.toJson(list, type.type, out)
            }

            override fun read(`in`: JsonReader): T {
                return when (`in`.peek()) {
                    JsonToken.BEGIN_ARRAY -> gson.fromJson(`in`, type.type)
                    JsonToken.BEGIN_OBJECT -> {
                        // 将单个对象包装为List返回
                        val element = elementAdapter.read(`in`)
                        Collections.singletonList(element) as T
                    }
                    else -> throw JsonParseException("Expected BEGIN_ARRAY or BEGIN_OBJECT but was ${`in`.peek()}")
                }
            }
        }
    }
}

3. 数据类中使用注解

data class CartResponse(
    @SingleOrList
    val items: List<OfferItem>,
    // 其他字段...
)

data class OfferItem(
    // 嵌套字段同样支持
    @SingleOrList
    val details: List<Detail>,
    // 其他字段...
)

场景2:Double类型响应转为Int存储

实现全局或字段级的Double转Int适配器:

全局Int类型适配(所有Int字段自动处理)

import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter

class DoubleToIntTypeAdapter : TypeAdapter<Int>() {
    override fun write(out: JsonWriter, value: Int) {
        // 写入时转回Double适配接口要求
        out.value(value.toDouble())
    }

    override fun read(`in`: JsonReader): Int {
        return when (`in`.peek()) {
            JsonToken.NUMBER -> `in`.nextDouble().toInt() // 直接取整,可按需改为四舍五入
            JsonToken.STRING -> `in`.nextString().toDouble().toInt() // 兼容字符串格式数字
            else -> throw JsonParseException("Expected NUMBER or STRING but was ${`in`.peek()}")
        }
    }
}

如果需要仅针对特定字段处理,可参考场景1的注解+Factory模式实现精准匹配。


整合到Dagger2配置

替换你现有的Gson提供逻辑,注册上述适配器和工厂:

@Provides
@Singleton
fun provideGson(): Gson {
    return GsonBuilder()
        .registerTypeAdapterFactory(SingleOrListTypeAdapterFactory())
        .registerTypeAdapter(Int::class.java, DoubleToIntTypeAdapter())
        .create()
}

@Provides
@Singleton
fun provideCartGsonConverterFactory(gson: Gson): GsonConverterFactory {
    return GsonConverterFactory.create(gson)
}

现有代码问题修正

你当前的CustomTypeAdapter和CustomTypeAdapterFactory存在逻辑错误:

  1. CustomTypeAdapter的write方法错误绑定了OfferItem::class.java,应动态使用传入的classOfT
  2. read方法存在非空类型赋值null、逻辑不完整的问题
  3. CustomTypeAdapterFactory仅处理Enum类型,不符合你的需求,建议替换为上述实现

内容的提问来源于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 11:45:37