kotlinx.serialization
kotlinx.serialization copied to clipboard
Polymorphic Deserialization Fails with Subclass using `JsonTransformingSerializer`
Describe the bug
In polymorphic deserialization, when the target subclass is using JsonTransformingSerializer, the deserialization will fail. It seems that it forgets it is deserializing an polymorphic object.
kotlinx.serialization.json.internal.JsonDecodingException: Encountered an unknown key 'type' at element: $
Use 'ignoreUnknownKeys = true' in 'Json {}' builder or '@JsonIgnoreUnknownKeys' annotation to ignore unknown keys.
JSON input: {"type":"Sub"}
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonTreeDecoder.endStructure(TreeJsonDecoder.kt:292)
at test.DecodeTest2$Sub$$serializer.deserialize(DecodeTest2.kt:15)
at test.DecodeTest2$Sub$$serializer.deserialize(DecodeTest2.kt:15)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:351)
at kotlinx.serialization.json.internal.TreeJsonDecoderKt.readJson(TreeJsonDecoder.kt:25)
at kotlinx.serialization.json.Json.decodeFromJsonElement(Json.kt:170)
at kotlinx.serialization.json.JsonTransformingSerializer.deserialize(JsonTransformingSerializer.kt:78)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:89)
at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
at test.DecodeTest2.test(DecodeTest2.kt:33)
To Reproduce
class DecodeTest2 {
@Serializable
sealed class Base
@OptIn(ExperimentalSerializationApi::class)
@Serializable(Sub.Serializer::class)
@KeepGeneratedSerializer
@SerialName("Sub")
class Sub : Base() {
object Serializer : JsonTransformingSerializer<Sub>(generatedSerializer())
}
@Test
fun test() {
val base: Base = Sub()
val jsonText = Json.encodeToString(base)
println(jsonText)
val decodedBase: Base = Json.decodeFromString(jsonText) // this will fail
println(decodedBase)
}
}
Expected behavior
The deserialization will succeed with a Sub instance.
Environment
- Kotlin version: 2.2.20
- Library version: 1.9.0
- Kotlin platforms: JVM
As a workaround, you can indeed use ignoreUnknownKeys. It seems that we 'forget' about class discriminator while going through JsonTransformingSerializer chain.