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

Retrofit同时注册Gson和Jackson转换器工厂的适配问题

解决方案

你的实现思路是完全正确的,Retrofit的ConverterFactory机制本身就支持返回null来跳过当前工厂,交给后续注册的其他工厂处理,你只需要在自定义的JacksonConverterFactory中增加「当前类型是否已注册自定义Jackson反序列化器」的判断逻辑即可。

核心判断逻辑

Jackson对所有内置的标准反序列化器都标记了@JacksonStdImpl注解,你可以通过ObjectMapper获取指定类型的实际生效反序列化器,判断是否存在该注解即可识别是不是自定义注册的反序列化器。

完整实现代码

1. 自定义Jackson转换器工厂

import com.fasterxml.jackson.databind.JacksonStdImpl
import com.fasterxml.jackson.databind.ObjectMapper
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Retrofit
import java.lang.reflect.Type

class CustomJacksonConverterFactory private constructor(
    private val mapper: ObjectMapper
) : Converter.Factory() {

    companion object {
        fun create(mapper: ObjectMapper): CustomJacksonConverterFactory {
            return CustomJacksonConverterFactory(mapper)
        }
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array<out Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *>? {
        val javaType = mapper.typeFactory.constructType(type)
        return try {
            // 获取该类型实际生效的反序列化器
            val deserializer = mapper.deserializationContext.findRootValueDeserializer(javaType)
            // 无@JacksonStdImpl注解则为自定义反序列化器
            val hasCustomDeserializer = deserializer.javaClass.getAnnotation(JacksonStdImpl::class.java) == null
            if (hasCustomDeserializer) {
                val reader = mapper.readerFor(javaType)
                JacksonResponseBodyConverter(reader)
            } else {
                // 返回null,交给下一个转换器工厂处理
                null
            }
        } catch (e: Exception) {
            // Jackson解析异常直接跳过,走后续Gson逻辑
            null
        }
    }

    private class JacksonResponseBodyConverter<T>(
        private val reader: ObjectReader
    ) : Converter<ResponseBody, T> {
        override fun convert(value: ResponseBody): T? {
            return value.use {
                reader.readValue(it.charStream())
            }
        }
    }

    // 如有请求体序列化需求,可按需重写requestBodyConverter方法,逻辑和上述类似
}

2. Retrofit初始化配置

注意转换器工厂的注册顺序,必须把自定义Jackson工厂放在Gson工厂前面:

// 初始化配置了自定义反序列化器的ObjectMapper
val module = SimpleModule()
module.addDeserializer(User::class.java, UserDeserializer())
val objectMapper = ObjectMapper()
objectMapper.registerModule(module)

val retrofit = Retrofit.Builder()
    .baseUrl("你的接口根地址")
    .addConverterFactory(CustomJacksonConverterFactory.create(objectMapper))
    // Jackson处理不了的请求会自动交给Gson处理
    .addConverterFactory(GsonConverterFactory.create())
    .build()

注意事项

  • 该逻辑同时适配普通类型、泛型类型(如List<User>)以及通过@JsonDeserialize注解标注的自定义反序列化场景。
  • 如有特殊类型需要强制走Jackson或Gson,可在判断逻辑中新增白名单/黑名单规则灵活调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:24:03