Skip to content

Incorrect SerialName used when using delegate serializer on a member of a sealed interface #2596

Closed
@FlorianDenis

Description

@FlorianDenis

Describe the bug

I have the suspicion that the incorrect SerialName is used when using a delegate serializer on a class implementing a sealed interface.
This could just be a configuration issue, but after carefully reading the doc, I cannot figure out what I am doing wrong.

To Reproduce
I have JSONs of the form

{"tag": "A"}
{"tag": "B", "field1": "someString"}
{"tag": "C", "aField": "someString", "anotherField": 42}

I am trying to build a sealed class hierarchy to read/write those here, only I want each individual data of the variant to be represented by a data class (for reuse, the same fields are used across several places with different "tag" discriminators depending on other factors)

@Serializable
data class MyReusedClass(
    val aField: String,
    val anotherField: UInt
)

@Serializable
@JsonClassDiscriminator("tag")
sealed interface MySealedInterface {
    @Serializable
    @SerialName("A")
    data object A : MySealedInterface // Works as you would expect

    @Serializable
    @SerialName("B")
    data class B(val field1: String) : MySealedInterface // Works as you would expect

    @Serializable(with = C.Serializer::class) // Delegating the serializer to `value` doesn't work here, the wrong "tag" is included
    data class C(val value: MyReusedClass) : MySealedInterface {
        object Serializer : KSerializer<C> {
            private val delegateSerializer = MyReusedClass.serializer()
            override val descriptor =
                SerialDescriptor("C", delegateSerializer.descriptor) // The serialName is supposed to be "C"

            override fun serialize(encoder: Encoder, value: C) {
                encoder.encodeSerializableValue(delegateSerializer, value.value)
            }

            override fun deserialize(decoder: Decoder): C {
                return C(decoder.decodeSerializableValue(delegateSerializer))
            }
        }
    }
}

Expected behavior

When serializing MySealedInterface.C(MyReusedClass("someString", 42u)) into JSON, I get
{"tag": "C", "aField": "someString", "anotherField": 42}

Actual behavior

When serializing MySealedInterface.C(MyReusedClass("someString", 42u)) into JSON, I get
{"tag": "my.package.name.MyReusedClass", "aField": "someString", "anotherField": 42}

Environment

  • Kotlin version: 1.9.10
  • Library version: 1.6.0
  • Kotlin platforms: Android
  • Gradle version: 8.0
  • IDE version: Android Studio 2022.3.1 Patch 1

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions