Skip to content

Polymorphic Serialization Mistakenly Triggered for Generic Property with Directly Serializable Type #2953

Closed
@CyanTachyon

Description

@CyanTachyon

Describe the bug
When serializing a sealed interface's generic property with a directly serializable type (e.g., Int or another @serializable class), the Kotlinx Serialization library incorrectly attempts polymorphic serialization, leading to a SerializationException.

To Reproduce

import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule

@Serializable
sealed interface Test<X>
{
    val x: X
}

@Serializable
data class Test1<Y>(override val x: Y): Test<Y>

@Serializable
data class Test2(val x: Int)

fun main()
{
    val json = Json {
        serializersModule = SerializersModule {
            contextual(Int::class, Int.serializer())
            contextual(Test2::class, Test2.serializer())
        }
    }
    val x: Test<Int> = Test1(1)
    val y: Test<Test2> = Test1(Test2(1))
    runCatching { json.encodeToString(x) }.onFailure(Throwable::printStackTrace) // error
    runCatching { json.encodeToString(y) }.onFailure(Throwable::printStackTrace) // error
}

error:

kotlinx.serialization.SerializationException: Serializer for subclass 'Int' is not found in the polymorphic scope of 'Any'.
Check if class with serial name 'Int' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'Int' has to be '@Serializable', and the base class 'Any' has to be sealed and '@Serializable'.
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102)
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:114)
	at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:250)
	at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80)
	at Test1.write$Self$KotlinTest(Main2.kt:12)
	at Test1$$serializer.serialize(Main2.kt:12)
	at Test1$$serializer.serialize(Main2.kt:12)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:259)
	at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:99)
	at kotlinx.serialization.json.Json.encodeToString(Json.kt:125)
	at Main2Kt.main(Main2.kt:32)
	at Main2Kt.main(Main2.kt)
kotlinx.serialization.SerializationException: Serializer for subclass 'Test2' is not found in the polymorphic scope of 'Any'.
Check if class with serial name 'Test2' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'Test2' has to be '@Serializable', and the base class 'Any' has to be sealed and '@Serializable'.
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102)
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:114)
	at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:250)
	at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80)
	at Test1.write$Self$KotlinTest(Main2.kt:12)
	at Test1$$serializer.serialize(Main2.kt:12)
	at Test1$$serializer.serialize(Main2.kt:12)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:259)
	at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:99)
	at kotlinx.serialization.json.Json.encodeToString(Json.kt:125)
	at Main2Kt.main(Main2.kt:33)
	at Main2Kt.main(Main2.kt)

Expected behavior
no error and successful serialization

Environment

  • Kotlin version: 2.1.10
  • Library version: 1.8.0
  • Kotlin platforms: JVM
  • Gradle version: 8.7

My English is not good, and some of the above content is from AI translation. If it is inaccurate, please forgive me.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions