Retrofit 2 .1.0 + Gson.序列化@车身,这是子类

dnph8jn4  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(143)

我有一个问题与Retrofit,它使用类的静态类型,而不是运行时类型序列化它的RequestBody。
假设我有两个类:

class A{
   String a;
}

class B extends A{
   String b;
}

现在我想提一个要求:

@Post("/someUrl)
Observable<Void> someRequest(@Body A body);

我想将A或B示例传递给someRequest,并根据类类型正确地序列化它们。
我试着使用RuntimeTypeAdapterFactory,它运行得很好,但是它在序列化后给了我额外的字段(类型字段)。我的A,B类将只用于序列化。

iih3973s

iih3973s1#

考虑只重载方法本身:

@Post("/someUrl)
Observable<Void> someRequest(@Body A body);
@Post("/someUrl)
Observable<Void> someRequest(@Body B body);
kuuvgm7e

kuuvgm7e2#

我知道,这个问题是老问题了,但真正正常的解决方案是在创建Retrofit示例时注册自定义类型适配器。例如here
它还可以与Kotlin密封类一起使用:

sealed class AbstractBody(val bodyType: String) {

    data class A(
        val someDataA: String
    ) : AbstractBody(bodyType = "A")

    data class B(
        val someDataB: String
    ) : AbstractBody(bodyType = "B")
}

而在你的改造创造者:

private fun createRetrofit(baseUrl: String, okHttpClient: OkHttpClient) =
    Retrofit.Builder()
        .baseUrl(baseUrl)
        .client(okHttpClient)
        .addConverterFactory(
            GsonConverterFactory.create(GsonBuilder().withCustomAdapters().create())
        )
        .build()

private fun GsonBuilder.withCustomAdapters() = apply {
    registerTypeAdapter(
        AbstractBody::class.java,
        JsonSerializer<AbstractBody> { src, _, context ->
            when (src) {
                is AbstractBody.A ->
                    context.serialize(src, AbstractBody.A::class.java)
                is AbstractBody.B ->
                    context.serialize(src, AbstractBody.B::class.java)
            }
        }
    )
}

相关问题