I encountered a confusing exception when writing JsonElement-related tests. I don't know how likely someone would be to stumble across this in the wild.
While it isn't a bug per se, the exception message could be clarified to point out the actual failure cause.
java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.remove(ArrayList.java:536)
at kotlinx.serialization.internal.TaggedDecoder.popTag(Tagged.kt:321)
at kotlinx.serialization.internal.TaggedDecoder.decodeBoolean(Tagged.kt:223)
at kotlinx.serialization.internal.BooleanSerializer.deserialize(Primitives.kt:86)
at kotlinx.serialization.internal.BooleanSerializer.deserialize(Primitives.kt:82)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:51)
at kotlinx.serialization.json.internal.TreeJsonDecoderKt.readJson(TreeJsonDecoder.kt:24)
at kotlinx.serialization.json.Json.decodeFromJsonElement(Json.kt:119)
To Reproduce
Consider the following (contrived) code:
fun main() {
val jsonString = JsonPrimitive("bar")
val jsonObject = JsonObject(mapOf("foo" to jsonString))
val jsonArray = JsonArray(listOf(jsonObject))
listOf(jsonString, jsonObject, jsonArray).forEach { element ->
runCatching { Json.decodeFromJsonElement<String>(element) }
.fold(
onSuccess = { println("Value is: $value") },
onFailure = { println("Could not decode element: ${it.message}") }
)
}
}
Attempting to decode JsonObject or JsonArray as a primitive (String, Boolean, Long, etc.) will yield the confusing error mentioned above.
Provide a meaningful exception, if possible. For example, attempting to decode a JsonObject or JsonArray as a JsonPrimitive yields a more friendly error:
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON element, expected JsonPrimitive, had class kotlinx.serialization.json.JsonObject
JSON input: {}
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.JsonPrimitiveSerializer.deserialize(JsonElementSerializers.kt:76)
at kotlinx.serialization.json.JsonPrimitiveSerializer.deserialize(JsonElementSerializers.kt:59)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:51)
at kotlinx.serialization.json.internal.TreeJsonDecoderKt.readJson(TreeJsonDecoder.kt:24)
at kotlinx.serialization.json.Json.decodeFromJsonElement(Json.kt:119)
Description
I encountered a confusing exception when writing JsonElement-related tests. I don't know how likely someone would be to stumble across this in the wild.
While it isn't a bug per se, the exception message could be clarified to point out the actual failure cause.
To Reproduce
Consider the following (contrived) code:
Attempting to decode
JsonObject
orJsonArray
as a primitive (String, Boolean, Long, etc.) will yield the confusing error mentioned above.https://github.com/Kotlin/kotlinx.serialization/blob/43d5f7841fc744b072a636b712e194081456b5ba/core/commonMain/src/kotlinx/serialization/internal/Tagged.kt#L320-L324
Expected behavior
Provide a meaningful exception, if possible. For example, attempting to decode a
JsonObject
orJsonArray
as aJsonPrimitive
yields a more friendly error:Environment