android - 在 Moshi 中考虑可为 null 的值

标签 android kotlin moshi

我有一个这样定义的类:

@JsonClass(generateAdapter = true)
data class CurrentWeather(
    @Json(name = "coord") val coordinates: Coordinates,
    @Json(name = "weather") val condition: List<Condition>,
    @Json(name = "base") val base: String,
    @Json(name = "main") val weatherCondition: Weather,
    @Json(name = "wind") val windCondition: Wind,
    @Json(name = "clouds") val cloudCondition: Cloud,
    @Json(name = "rain") val rainCondition: Rain,
    @Json(name = "snow") val snowCondition: Snow,
    @Json(name = "dt") val date: Double,
    @Json(name = "sys") val sysCondition: Sys,
    @Json(name = "id") val cityId: Long,
    @Json(name = "name") val cityName: String,
    @Json(name = "cod") val status: Int
)

问题是,在获取我的 JSON 数据时,其中一些值可能为 null,也可能不为 null。为此,我曾尝试在字段名称和/或类名称之前附加 @Nullable,但遗憾的是这种方法不起作用。尝试使用或不使用 @Nullable 都会给我同样的错误:

2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err: com.squareup.moshi.JsonDataException: Required value 'message' missing at $.sys
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.Util.missingProperty(Util.java:605)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.SysJsonAdapter.fromJson(SysJsonAdapter.kt:59)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.SysJsonAdapter.fromJson(SysJsonAdapter.kt:16)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.CurrentWeatherJsonAdapter.fromJson(CurrentWeatherJsonAdapter.kt:98)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.CurrentWeatherJsonAdapter.fromJson(CurrentWeatherJsonAdapter.kt:19)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:45)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:27)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2019-11-19 16:52:37.677 1544-1544/com.a5corp.weather W/System.err:     at java.lang.Thread.run(Thread.java:919)

我通过以下方式将 Moshi 与 Retrofit 结合使用:

fun retrofit(url: String): Retrofit = Retrofit.Builder()
        .client(owmClient)
        .baseUrl(url)
        .addConverterFactory(MoshiConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .build()

那么有什么方法可以在 Moshi 中容纳 Nullable 值吗?

编辑 1:我现在更改了我的类(class),以便在下面的答案中适应@sasikumar 提供的解决方案,但现在它给了我另一个新错误:

2019-11-19 18:27:00.753 21530-21530/com.a5corp.weather W/System.err: java.lang.NoSuchMethodException: com.a5corp.weather.model.Condition.<init> [int, class java.lang.String, int, class kotlin.jvm.internal.DefaultConstructorMarker]
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at java.lang.Class.getConstructor0(Class.java:2332)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at java.lang.Class.getDeclaredConstructor(Class.java:2170)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.ConditionJsonAdapter.fromJson(ConditionJsonAdapter.kt:62)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.ConditionJsonAdapter.fromJson(ConditionJsonAdapter.kt:18)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.squareup.moshi.CollectionJsonAdapter.fromJson(CollectionJsonAdapter.java:76)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.squareup.moshi.CollectionJsonAdapter$2.fromJson(CollectionJsonAdapter.java:53)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.CurrentWeatherJsonAdapter.fromJson(CurrentWeatherJsonAdapter.kt:95)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.a5corp.weather.model.CurrentWeatherJsonAdapter.fromJson(CurrentWeatherJsonAdapter.kt:22)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:45)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:27)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2019-11-19 18:27:00.754 21530-21530/com.a5corp.weather W/System.err:     at java.lang.Thread.run(Thread.java:919)

从第一行开始,我无法弄清楚它的意思,但我的 Condition 类定义如下:

@JsonClass(generateAdapter = true)
data class Condition(
    @Json(name = "id") val id: Int? = null,
    @Json(name = "description") val description: String? = null
)

编辑 2:它基本上是 OWM API:https://openweathermap.org/current但我的 JSON 数据在这里:

{
  "coord": {
    "lon": 77.59,
    "lat": 12.98
  },
  "weather": [
    {
      "id": 802,
      "main": "Clouds",
      "description": "scattered clouds",
      "icon": "03n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 26.62,
    "pressure": 1015,
    "humidity": 69,
    "temp_min": 23,
    "temp_max": 29.44
  },
  "visibility": 8000,
  "wind": {
    "speed": 3.1,
    "deg": 80
  },
  "clouds": {
    "all": 40
  },
  "dt": 1574169845,
  "sys": {
    "type": 1,
    "id": 9205,
    "country": "IN",
    "sunrise": 1574124599,
    "sunset": 1574166006
  },
  "timezone": 19800,
  "id": 1277333,
  "name": "Bengaluru",
  "cod": 200
}

最佳答案

对于 null 的情况应该是

@JsonClass(generateAdapter = true)
data class CurrentWeather(val base: String?=null)

像这样做其他可为空的参数。

编辑 你应该为上面的 json 创建这样的数据类

data class Clouds(
val all: Int)

data class Condition(
val base: String,
val clouds: Clouds,
val cod: Int,
val coord: Coord,
val dt: Int,
val id: Int,
val main: Main,
val name: String,
val sys: Sys,
val timezone: Int,
val visibility: Int,
val weather: List<Weather>,
val wind: Wind
)

data class Coord(
val lat: Double,
val lon: Double
 )


data class Main(
val humidity: Int,
val pressure: Int,
val temp: Double,
val temp_max: Double,
val temp_min: Int
)

data class Sys(
val country: String,
val id: Int,
val sunrise: Int,
val sunset: Int,
val type: Int
 )

data class Weather(
val description: String,
val icon: String,
val id: Int,
val main: String
)


data class Wind(
val deg: Int,
val speed: Double
)

关于android - 在 Moshi 中考虑可为 null 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58934004/

相关文章:

Android ffmpeg 保存并 append h264 流视频

android - 如何在抽屉导航中放置项目图标

linux - 为什么 Gradle 在 :linkDebugTestLinux in my Kotlin multiplatform project? 上失败

android - 使用 Moshi 处理损坏的服务器响应

java - 在 Android studio : Kotlin 中保存实例状态

android - 无法在 android 中播放超过 7 次的声音

kotlin - 如何在 Ktor 内部检查 Netty 是否实际启动?

javascript - Kotlin XML 解析

generics - 用于通用列表的 Moshi 自定义适配器 <T :Enum> returns List<List<T:Enum>> instead of List<T:Enum>

android - moshi 自定义 JsonAdapter 跳过坏元素的问题