I have a data class:
data class Example(
@SerializedName("id")
val id: String,
@SerializedName("url")
val url: String,
@SerializedName("more")
val more: String = "",
)
When I use Gson to instantiate Example
:
val example1 = Gson().fromJson("{id: 1}", Example::class.java)
val example2 = Gson().fromJson("{id: 2}", Example::class.java)
I got two examples whose url is null, because there is no value for url.
Look at this expression:
val url: String = example1?.url ?: example2?.url ?: "aaaaaaaaaa"
println("url:$url")
I got url:null
But the expression below prints the default value url:aaaaaaaaaa
:
val url: String = example1.url ?: example2.url ?: "aaaaaaaaaa"
println("url:$url")
Any body knows why? It is supposed to return the default value.
I have a data class:
data class Example(
@SerializedName("id")
val id: String,
@SerializedName("url")
val url: String,
@SerializedName("more")
val more: String = "",
)
When I use Gson to instantiate Example
:
val example1 = Gson().fromJson("{id: 1}", Example::class.java)
val example2 = Gson().fromJson("{id: 2}", Example::class.java)
I got two examples whose url is null, because there is no value for url.
Look at this expression:
val url: String = example1?.url ?: example2?.url ?: "aaaaaaaaaa"
println("url:$url")
I got url:null
But the expression below prints the default value url:aaaaaaaaaa
:
val url: String = example1.url ?: example2.url ?: "aaaaaaaaaa"
println("url:$url")
Any body knows why? It is supposed to return the default value.
Share Improve this question edited Feb 1 at 13:07 tyg 16.2k4 gold badges36 silver badges48 bronze badges asked Feb 1 at 12:42 GarfieldmaoGarfieldmao 111 silver badge1 bronze badge 1- 1 gson+kotlin tags combined make me cringe every time. Consider kotlinx.serialization or other solution that has actual kotlin support and does not rely on brutal reflection to spawn the objects. – Pawel Commented Feb 1 at 13:04
1 Answer
Reset to default 2This appears to be a compiler bug. By inspecting the bytecode, both there are null checks on example1
, example1.url
, and example2
, but not example2.url
.
A change as simple as:
val x = example1?.url
val url: String = x ?: example2?.url ?: "aaaaaaaaaa"
produces the expected output.
This is likely due to your declaring url
as non-nullable, but Gson setting it to null anyway. If you change url
to a nullable type, the code produces the expected output too.
data class Example(
// these SerializedNames are also redundant
@SerializedName("id")
val id: String,
@SerializedName("url")
val url: String?,
@SerializedName("more")
val more: String = "",
)
The same thing applies to the more
property. Gson will not see the = ""
default parameter value, and sets more
to null if the key does not exist in the JSON. Generally, Gson is not suitable for use with Kotlin. See these related posts: 1, 2.
From this answer, it seems like jackson-module-kotlin can recognise default values like this, so consider using Jackson instead.