Kotlin + Retrofit + Gson 反序列化不适用于嵌套 json

Kotlin + Retrofit + Gson Deserializing not working for nested json

我正在使用 Kotlin 和 retrofit+gson 进行网络调用,但我无法反序列化嵌套的响应 json

这是我的网络模块

class NetworkModule() {

@Provides
internal fun provideGson(): Gson {
    return GsonBuilder()
            .setLenient()
            .disableHtmlEscaping()
            .create()
}


@Provides
internal fun provideOkHttpClient(): OkHttpClient {
    val builder = OkHttpClient.Builder()
    builder.readTimeout(60, TimeUnit.SECONDS)
    builder.connectTimeout(60, TimeUnit.SECONDS)
    val logging = HttpLoggingInterceptor()
    logging.level = HttpLoggingInterceptor.Level.BODY
    val client = OkHttpClient.Builder()
            .addInterceptor(logging)
            .build()

    return client
}

@Provides
internal fun provideLuqyaApi(gson: Gson, okHttpClient: OkHttpClient): LuqyaApi {
    return Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL_PLUS)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            .build().create(LuqyaApi::class.java)
}

这是模型

data class HomeResponse(

    @field:SerializedName("code")
    @Expose
val code: String? = null,

    @field:SerializedName("data")
    @Expose
val homeDataItem: HomeDataItem,

    @field:SerializedName("message")
    @Expose
val message: String? = null,

    @field:SerializedName("notifications")
    @Expose
val notifications: Int? = null

)

class HomeDataItem {
@SerializedName("specialEvent")
val specialEvent: SpecialEvent?=null

@SerializedName("homeAdvertisment")
val homeAdvertisment: HomeAdvertisment?=null

@SerializedName("locations")
val locations=ArrayList<LocationsItem>()
}

我收到这样的回复

HomeResponse(code=201, homeDataItem=m.a.b.b.a.b.b@ada2b35, message=All home locations and an advertisement, notifications=16)

这里有什么问题吗?

好吧,您正在使用 val 来定义元素并为它们分配空值。这意味着这些元素不会在响应到来时更新。

val 不允许更改变量值,请改用 var

m.a.b.b.a.b.b@ada2b35其实是一个引用地址,存放的地址。

既没有HomeDataItem实现toString()也不是数据class。

数据反序列化正确,您也可以访问了。但是如果你调用 println 它将触发它的默认 toString 实现,它 returns 它的参考地址。

解决方法 1: 自己创建 toString:

fun toString() =
    "HomeDataItem(specialEvent=$specialEvent, homeAdvertisment=$homeAdvertisment, locations=$locations)"

解决方法 2:只需将 HomeDataItem 设为数据 class,它将为您生成 toString


注意:

您必须将变量放在构造函数中,您目前已将它们设为实例变量并为它们分配了 null。

class HomeDataItem (
@SerializedName("specialEvent")
val specialEvent: SpecialEvent?=null

@SerializedName("homeAdvertisment")
val homeAdvertisment: HomeAdvertisment?=null

@SerializedName("locations")
val locations=ArrayList<LocationsItem>()
)

已解决 似乎这是 R8 和 GSON 之间的问题,可以通过将这些行添加到 proguard 规则来解决

-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation @interface com.google.gson.annotations.SerializedName