Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON: Decode nullable enum property from JsonElement with non-explicit nulls throws NoSuchElementException #2931

Closed
damianw opened this issue Feb 18, 2025 · 1 comment

Comments

@damianw
Copy link

damianw commented Feb 18, 2025

When decoding a nullable enum property from a JsonElement, using explicitNulls = false, the absence of the field results in deserialization throwing a NoSuchElementException with message Key ... is missing in the map..

This behavior appears specific to 1) decoding from a JsonElement and 2) the property being an enum. The same problem doesn't occur either when decoding from string, or when the property is any other kind of type.

To Reproduce

The below sample can be ran directly on the Kotlin Playground here.

package sample

import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.put
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable

@Serializable
data class Thing(
    val required: String,
    val nullable: Type?,
)

@Serializable
enum class Type {
    FOO,
    BAR,
}

fun main() {
    val json = Json {
        coerceInputValues = true
        ignoreUnknownKeys = true
        encodeDefaults = true
        explicitNulls = false
    }
    val element = buildJsonObject {
        put("required", "blah")
    }
    val result = json.decodeFromJsonElement<Thing>(element)
    println(result)
}

Exception:

Exception in thread "main" java.util.NoSuchElementException: Key nullable is missing in the map.
 at kotlin.collections.MapsKt__MapWithDefaultKt.getOrImplicitDefaultNullable (MapWithDefault.kt:24) 
 at kotlin.collections.MapsKt__MapsKt.getValue (Maps.kt:369) 
 at kotlinx.serialization.json.internal.JsonTreeDecoder.currentElement (TreeJsonDecoder.kt:255) 

Expected behavior

Decoding the JsonObject should not throw an exception; instead it should default the value of nullable to null. This works correctly when using decodeFromString: if the val result = ... line in the reproduction sample is changed to val result = json.decodeFromString<Thing>("""{"required": "blah"}"""), the test passes successfully.

Environment

  • Kotlin version: 2.0.20 in local reproduction project, 2.1.10 in Kotlin Playground
  • Library version: 1.7.3 in local reproduction project, unknown in Kotlin Playground (probably 1.8.0)
  • Kotlin platforms: JVM, JS
  • Gradle version: N/A
@sandwwraith
Copy link
Member

I think it is the same bug as in #2909. coerceInputValues working incorrectly when deserializing from JsonObject.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants