【问题标题】:Kotlin + Retrofit + Gson Deserializing not working for nested jsonKotlin + Retrofit + Gson 反序列化不适用于嵌套的 json
【发布时间】:2020-04-27 16:15:04
【问题描述】:

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

这是我的网络模块

类 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=所有家庭位置和一个广告,notifications=16)

这里有什么问题?

【问题讨论】:

    标签: android kotlin gson retrofit2


    【解决方案1】:

    您使用 val 来定义元素并为它们分配空值。这意味着当响应进来时这些元素不会被更新。

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

    【讨论】:

    • 在所有模型中将所有 val 更改为 var 并且仍然得到相同的响应。
    【解决方案2】:

    m.a.b.b.a.b.b@ada2b35实际上是一个引用地址,就是存储它的地址。

    HomeDataItem 既不是实现toString() 也不是数据类。

    数据已正确反序列化,您也可以访问它。但是如果你调用 println,它会触发它默认的toString 实现,返回它的引用地址。

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

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

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


    注意:

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

    class HomeDataItem (
    @SerializedName("specialEvent")
    val specialEvent: SpecialEvent?=null
    
    @SerializedName("homeAdvertisment")
    val homeAdvertisment: HomeAdvertisment?=null
    
    @SerializedName("locations")
    val locations=ArrayList<LocationsItem>()
    )
    

    【讨论】:

    • 所以我将 HomeDataItem 更改为 Data Class,但仍然得到相同的响应,并且无法访问其中的任何内部对象、字段。
    • @Elshawaf 您是否将字段更改为在构造函数中?而不是包裹在正文中 {} 放入 () 我已经在答案中用注释显示了它。
    • 是的,当然,已经将普通类更改为数据类将让我将它们全部放在构造函数中 => HomeDataItem ()
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 1970-01-01
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多