1

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.

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. Commented Feb 1 at 13:04

1 Answer 1

2

This 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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer! But I am still puzzled, According to what you said, expression "val url: String = example1?.url ?: "aaaaaaaaaa"" or "val url: String = example1?.url ?: example2.url ?: "aaaaaaaaaa""should return null, but both of them return default value "aaaaaaaaaa". It seems that there are still some unknown mechanisms
@Garfieldmao Right. I think this is likely a compiler bug. Bottom line is, don't use Gson with Kotlin.
@Garfieldmao I have reported this as KT-74895.
Thanks a lot!!! I will also continue to pay attention to this issue!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.