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
我正在使用 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