Skip to content

Closed polymorphism default serializer annotation #1575

@juggernaut0

Description

@juggernaut0

What is your use-case and why do you need this feature?

With open polymorphism, you can specify a default serializer in your SerializersModule to handle unknown discriminator values:

val module = SerializersModule {
    polymorphic(Project::class) {
        subclass(OwnedProject::class)
        default { BasicProject.serializer() }
    }
}

(from https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md)

Here, if the discriminator does not match any known subclass' SerialName, default will be used.

Closed polymorphism (sealed classes) is often preferred because SerializersModule is not needed. However, default serializers become an issue then you would still need to register a default in a serializers module, even though the subclasses (and a potential default) are known at compile time. It would be useful to have a way to statically mark one of the subclasses as a default without the use of a SerializersModule to better support the simplicity of using closed polymorphism.

Describe the solution you'd like

I propose adding an @SerialDefault annotation (or a similar name) that performs the same function as default:

@Serializable
sealed class Project {
    abstract val name: String
}

@Serializable
@SerialDefault // Any unknown project types will be desearialized into a BasicProject
data class BasicProject(override val name: String, val type: String): Project()

@Serializable
@SerialName("OwnedProject")
data class OwnedProject(override val name: String, val owner: String) : Project()

The expected behaviour would be mostly the same as with open polymorphism: sealedClassSerializer.findPolymorphicSerializerOrNull(decoder, "unknown") would return the default serializer, but without decoder necessarily having a default registered in its serializersModule.

This could be implemented with an optional val defaultPolymorphicSerializer: DeserializationStrategy<out T>? = null field in SealedClassSerializer, and the implementation of findPolymorphicSerializerOrNull would have an extra ?: defaultPolymorphicSerializer

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions