简体   繁体   中英

Kotlin + Retrofit + Gson Deserializing not working for nested json

I'm using Kotlin and retrofit+gson for network calls and i'm not able to deserializing responses for nested json

Here's My Network Module

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)
}

here's the models

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>()
}

and i'm getting Responses like this

HomeResponse(code=201, homeDataItem= mabbabb@ada2b35 , message=All home locations and an advertisement, notifications=16)

What's wrong here?

Well you're using val for defining the elements and assigning a null value to them. Meaning that those elements won't be updated when response comes in.

val doesn't allow to change variable values, use var instead.

mabbabb@ada2b35 is actually a reference address, address at which it is stored.

Neither HomeDataItem implement toString() nor it is a data class.

The data is correctly deserialized, you can also access it. But if you call println it will trigger its default toString implementation which returns its reference address.

Workaround 1: Create your toString yourself:

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

Workaround 2: Just make the HomeDataItem a data class, it will generate toString for you.


NOTE:

You have to put your variables inside constructor, you currently have make them instance variable and assigned null to them.

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

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

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

SOLVED Seems it's a problem between R8 and GSON and it can be solved by adding these lines to proguard rules

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM