最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

json - kotlin why multiple elvis operator didn't return default value but null - Stack Overflow

programmeradmin0浏览0评论

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
Add a comment  | 

1 Answer 1

Reset to default 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.

发布评论

评论列表(0)

  1. 暂无评论