kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

Polymorphism with custom serializer which writes JsonObject outputs incorrect class discriminator

Open sandwwraith opened this issue 2 years ago • 0 comments

Describe the bug "type":"kotlin.collections.LinkedHashMap" is an incorrect discriminator and prevents data from de-serialization

To Reproduce

@Serializable
data class ValueHolder<V : Any>(
    val someField: Int,
    @Polymorphic val value: V,
)

@Serializable
data class DataStructure<V : Any>(
    val holders: List<ValueHolder<V>>
)

data class VImpl(val a: String, val b: Int)

class E {
    val serializer = object : KSerializer<VImpl> {
        override val descriptor: SerialDescriptor =
            buildClassSerialDescriptor("VImpl") {
                element("a", String.serializer().descriptor)
                element("b", Int.serializer().descriptor)
            }

        override fun deserialize(decoder: Decoder): VImpl {
            decoder as JsonDecoder
            val jsonObject = decoder.decodeJsonElement() as JsonObject
            return VImpl(
                (jsonObject["a"] as JsonPrimitive).toString(),
                (jsonObject["b"] as JsonPrimitive).int,
            )
        }

        override fun serialize(encoder: Encoder, value: VImpl) {
            encoder as JsonEncoder
            encoder.encodeJsonElement(
                JsonObject(
                    mapOf(
                        "a" to JsonPrimitive(value.a),
                        "b" to JsonPrimitive(value.b)
                    )
                )
            )
        }
    }


    @Test
    fun main() {
        val dataStructure = DataStructure(listOf(ValueHolder(0, VImpl("string", 1))))

        val json = Json {
            serializersModule = SerializersModule {
                polymorphic(Any::class, VImpl::class, serializer)
            }
        }

        val string = json.encodeToString(
            DataStructure.serializer(serializer),
            dataStructure
        )
        println(string)
    }

}

Expected behavior Data can be deserialized back

Environment

  • Kotlin version: 1.9.0
  • Library version: 1.6.0

sandwwraith avatar Sep 21 '23 18:09 sandwwraith