Reputation: 114
After kotlin being the first language for android, I have devoted myself into it. With a little progress over the days I have been migrating my existing knowledge to kotlin. Recently, I am learning how to use GSON, Retrofit and kotlin in a dummy project.
Here CurrentWeather
is the model which shows data in a view
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
is responsible to parse the JSON to POJO class just like I did in the past, but today it just looks a little different for using 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)
}
Even if I get a successful response from retrofit(I have checked the members variables; such as location: Location, weather: List, temperatureAndPressure: TemperatureAndPressure etc. However, I am getting this error.
2018-11-12 21:04:07.455 9948-9948/bus.green.fivedayweather E/AndroidRuntime: FATAL EXCEPTION: main Process: bus.green.fivedayweather, PID: 9948 java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter p1 at bus.green.fivedayweather.ui.CurrentWeatherFragment$retrieveForecast$1.invoke(Unknown Source:6) at bus.green.fivedayweather.ui.CurrentWeatherFragment$retrieveForecast$1.invoke(CurrentWeatherFragment.kt:20) at bus.green.fivedayweather.net.OpenWeatherMapProvider$RetrofitCallbackWrapper.onResponse(OpenWeatherMapProvider.kt:62)
Am I doing anything wrong in parsing?
Upvotes: 1
Views: 4716
Reputation: 2485
I believe if you follow the above solution by making your variable nullable type won't solve your problem. In your case problem lies in JSON parse for this case Gson itself. First of all, Gson has no native support for Kotlin data class. I would suggest you read through this article GSON+KOTLIN. A short summary of this writing is
val currentWeather
which is an instance of the data class and Gson which uses reflect can't instantiate it from deserialised JSON, hence it will be null even if you parse the member variables for data class Current
correctly.My suggestion would be a switch to Moshi, which has a built-in support for Kotlin.On the contrary, if you are an extreme fan of Gson, you need to follow this workaround with help of default value and making variables null type. For this, we basically have the constructor arguments be private backing properties. We then provide a read-only property for each backing field with the real name and use the custom get() = combined with the Elvis operator to define our default value or behavior, resulting in non-nullable return values.
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)
}
In my opinion, in these days of Kotlin ruling world Gson hasn't been able to keep up the pace. If you are just doing this project just for sake of learning, you should definitely use Moshi. it has KotlinJsonAdapterFactory
which has out-of-the-box support for JSON
Upvotes: 0
Reputation: 8200
this is your issue Parameter specified as non-null is null
. All your data classes are declared with non-null parameter constructor
. However, in parsing JSON process, there's a null parameter --> that made the crash. To solve this issue, you should declare constructor parameters as nullable as below:
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.
Upvotes: 7