Kotlinx.serialization: Support multiple class descriminators for polymorphism.

Created on 29 Aug 2019  Â·  8Comments  Â·  Source: Kotlin/kotlinx.serialization

What is your use-case and why do you need this feature?
As of writing this issue, only a single classDiscriminator can be specified on a Json object.
I'm working with a REST api where for different endpoints or error codes, the object returned will use a different "class discriminator".

For example, if the response code is != 200, then an error in form of JSON is returned.

The discriminator here is errcode.

sealed class MatrixError : Throwable() {
    abstract val errcode: String
}

@Serializable
@SerialName("M_NOT_FOUND")
data class NotFound(override val error: String) : MatrixError() {
    override val errcode get() = "M_NOT_FOUND"
}

@Serializable
@SerialName("M_LIMIT_EXCEEDED")
data class LimitExceeded(
    override val error: String,

    @SerialName("retry_after_ms")
    val retryAfterMillis: Long
) : MatrixError() {
    override val errcode get() = "M_LIMIT_EXCEEDED"
}

If the response code is 200, then the model uses type as the discriminator.

sealed class Event

@SerialName("m.room")
data class RoomEvent : Event

@SerialName("m.join")
data class JoinEvent(val userId: String) : Event

Describe the solution you'd like
I would like to be able to annotate the parent class with a discriminator.

Or supply a class discriminator in the module like so.

SerializersModule {
    polymorphic<MatrixError>(discriminator="errcode") {
        addSubclass(MatrixError.Unknown.serializer())
        addSubclass(MatrixError.NotFound.serializer())
        addSubclass(MatrixError.Forbidden.serializer())
        addSubclass(MatrixError.UnsupportedRoomVersion.serializer())
        addSubclass(MatrixError.LimitExceeded.serializer())
   }
}
feature

Most helpful comment

This is not being worked on, but it seems to me that it requires some additional handling from plugin: @SerialInfo annotations are not stored when used on abstract classes, so it's impossible to retrieve smth like

@JsonTypeDiscriminator("errcode")
@Serializable
abstract class ErrCode

Although it is still possible to configure from polymorphic { } builder, I'm not sure this is a great idea because builders and modules should be format-agnostic.

All 8 comments

Would a PR for this be accepted or is this already being worked on?

This is not being worked on, but it seems to me that it requires some additional handling from plugin: @SerialInfo annotations are not stored when used on abstract classes, so it's impossible to retrieve smth like

@JsonTypeDiscriminator("errcode")
@Serializable
abstract class ErrCode

Although it is still possible to configure from polymorphic { } builder, I'm not sure this is a great idea because builders and modules should be format-agnostic.

Is it possible to enable storage of @SerialInfo annotations in the serializers of abstract classes?

For the time being, how should we configure class discriminator in polymorphic { } as you mentioned? @sandwwraith

When an abstract class ExampleClass is annotated with @Serializable, what does ExampleClass.serializer() return?
Can the plugin pass the class discriminator in to the ctor of the generated serializer?

@giangpham96 It is not implemented yet.

@Dominaezzz It is possible, although it requires changes in the plugin — and the proper solution (store serialinfo/serialname annotations in PolymorphicSerializer) requires them too

any news on this one? it's extremely desirable feature for us

Probably waiting for 1.5.0 when most of the backends will be IR based.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

daweedm picture daweedm  Â·  4Comments

ersin-ertan picture ersin-ertan  Â·  3Comments

Chris-Corea picture Chris-Corea  Â·  3Comments

SaifurRahmanMohsin picture SaifurRahmanMohsin  Â·  3Comments

sandwwraith picture sandwwraith  Â·  4Comments