java.lang.IllegalArgumentException: параметр, указанный как ненулевой, является нулем, анализируя JSON к kotlin Классу данных - PullRequest
0 голосов
/ 12 ноября 2018

После того, как kotlin стал первым языком для Android, я посвятил себя этому. С небольшим прогрессом за эти дни я перенес свои знания в kotlin. Недавно я учусь использовать GSON, Retrofit и kotlin в фиктивном проекте.

Здесь CurrentWeather - модель, которая показывает данные в виде

data class CurrentWeather(
    val latitude: Double,
    val longitude: Double,
    val placeName: String,
    val temperature: Float,
    val maxTemperature: Float,
    val minTemperature: Float,
    val windSpeed: Float,
    val windDirection: Float,
    val weatherType: String,
    val weatherDescription: String,
    val icon: String,
    val timestamp: Instant)

class Current отвечает за синтаксический анализ класса JSON в POJO, как я это делал раньше, но сегодня он выглядит немного иначе при использовании kotlin

data class Current(@SerializedName("coord") val location: Location,
          @SerializedName("weather") val weather: List<Weather>,
          @SerializedName("main") val temperatureAndPressure: TemperatureAndPressure,
          @SerializedName("wind") val wind: Wind,
          @SerializedName("dt") val timeStamp: Long,
          @SerializedName("name") val placeName: String) {

val time: Instant by fastLazy { Instant.ofEpochSecond(timeStamp) }


val currentWeather = CurrentWeather(location.latitude,
        location.longitude,
        placeName,
        temperatureAndPressure.temperature,
        temperatureAndPressure.maxTemperature,
        temperatureAndPressure.minTemperature,
        wind.windSpeed ?: 0f,
        wind.windAngle ?: 0f,
        weather[0].main,
        weather[0].description,
        weather[0].icon,
        time)
 }

Даже если я получаю успешный ответ от модернизации (я проверил переменные членов; например, местоположение: местоположение, погода: список, температура, давление, температура, давление и т. Д. Однако, я получаю эту ошибку.

2018-11-12 21: 04: 07.455 9948-9948 / bus.green.fivedayweather E / AndroidRuntime: ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: основное Процесс: bus.green.fivedayweather, PID: 9948 java.lang.IllegalArgumentException: параметр, указанный как ненулевой, является нулем: метод kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, параметр p1 на bus.green.fivedayweather.ui.CurrentWeatherFragment $ retrieveForecast $ 1.invoke (неизвестный источник: 6) на bus.green.fivedayweather.ui.CurrentWeatherFragment $ retrieveForecast $ 1.invoke (CurrentWeatherFragment.kt: 20) на bus.green.fivedayweather.net.OpenWeatherMapProvider $ RetrofitCallbackWrapper.onResponse (OpenWeatherMapProvider.kt: 62)

Я что-то не так делаю в разборе?

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Я полагаю, что если вы последуете вышеуказанному решению, сделав тип переменной nullable, это не решит вашу проблему. В вашем случае проблема заключается в JSON-разборе для этого случая самого Gson. Прежде всего, Gson не имеет встроенной поддержки класса данных Kotlin. Я бы предложил вам прочитать эту статью GSON + KOTLIN . Краткое содержание этого письма:

  1. Это особенно ужасно, когда мы учитываем предположение о нулевой безопасности разработчика при использовании ненулевых типов. Это приведет к исключению NullPointerException во время выполнения без намеков со стороны IDE о возможной обнуляемости. Мы даже не получим исключение при разборе, потому что Gson использует небезопасное отражение, а Java не имеет понятия о ненулевых типах.
  2. Один из способов справиться с этим - сдаться и сделать все обнуляемым, как ответ, предложенный @Kingfisher Phuoc. К сожалению, это не только заставит код работать. Причина в том, что ваша переменная-член val currentWeather является экземпляром класса данных, и Gson, использующий отражение, не может создать его экземпляр из десериализованного JSON, поэтому он будет нулевым, даже если вы правильно проанализируете переменные-члены для data class Current.

Мое предложение было бы переключиться на Moshi , который имеет встроенную поддержку Kotlin. Наоборот, если вы преданный поклонник Gson, вам нужно следовать этому обходному пути с помощью значение по умолчанию и создание переменных нулевого типа. Для этого у нас в основном есть аргументы конструктора - частные свойства поддержки. Затем мы предоставляем свойство только для чтения для каждого вспомогательного поля с реальным именем и используем пользовательский метод get () = в сочетании с оператором Elvis для определения значения или поведения по умолчанию, что приводит к ненулевым возвращаемым значениям.

data class Current(@SerializedName("coord") val _location: Location?,
      @SerializedName("weather") val _weather: List<Weather>?,
      @SerializedName("main") val _temperatureAndPressure: TemperatureAndPressure?,
      @SerializedName("wind") val _wind: Wind?,
      @SerializedName("dt") val _timeStamp: Long?, = 0.0
      @SerializedName("name") val _placeName: String? = "") {


val location
   get() = _location ?: throw IllegalArgumentException("Location is required")
val weather
   get() = _weather ?: throw IllegalArgumentException("Title is required")
val wind
   get() = _wind ?: throw IllegalArgumentException("Title is required")
val temperatureAndPressure
   get() = _temperatureAndPressure ?: throw IllegalArgumentException("Title is required")
......and so on



val time: Instant by fastLazy { Instant.ofEpochSecond(timeStamp) }


val currentWeather = CurrentWeather(location.latitude,
    location.longitude,
    placeName,
    temperatureAndPressure.temperature,
    temperatureAndPressure.maxTemperature,
    temperatureAndPressure.minTemperature,
    wind.windSpeed ?: 0f,
    wind.windAngle ?: 0f,
    weather[0].main,
    weather[0].description,
    weather[0].icon,
    time)
}

По моему мнению, в эти дни правящего мира Котлина Гсону не удавалось идти в ногу. Если вы просто делаете этот проект ради обучения, вам определенно следует использовать Moshi. он имеет KotlinJsonAdapterFactory, который имеет встроенную поддержку JSON

0 голосов
/ 12 ноября 2018

это ваша проблема Parameter specified as non-null is null. Все ваши классы данных объявлены с non-null parameter constructor. Однако при разборе JSON-процесса есть нулевой параметр ->, вызвавший сбой. Чтобы решить эту проблему, вы должны объявить параметры конструктора как обнуляемые, как показано ниже:

data class Current(@SerializedName("coord") val location: Location?,
      @SerializedName("weather") val weather: List<Weather>?,
      @SerializedName("main") val temperatureAndPressure: TemperatureAndPressure?,
      @SerializedName("wind") val wind: Wind?,
      @SerializedName("dt") val timeStamp: Long?,
      @SerializedName("name") val placeName: String?) {
// your CurrentWeather class should be the same. 
// Of course, if you are sure with non-null parameters, you should make them non-null.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...