quicktype icon indicating copy to clipboard operation
quicktype copied to clipboard

Generated kotlinX code fails to serialize enums properly

Open 0us opened this issue 5 years ago • 3 comments

I am facing a problem when generating kotlinX code from json schema.

Quicktype generates a custom serializer for each enum, looking like this:

@Serializable
enum class MessageFunction(val value: String) {
    Autp("AUTP"),
    Autq("AUTQ"),
    .
    .
    .

    companion object :
        KSerializer<MessageFunction> {
        override val descriptor: SerialDescriptor
            get() {
                return PrimitiveSerialDescriptor(
                    "MessageFunction",
                    PrimitiveKind.STRING
                )
            }

        override fun deserialize(decoder: Decoder): MessageFunction =
            when (val value = decoder.decodeString()) {
                "AUTP" -> Autp
                "AUTQ" -> Autq
                .
                .
                .
                else -> throw IllegalArgumentException("MessageFunction could not parse: $value")
            }

        override fun serialize(
            encoder: Encoder,
            value: MessageFunction
        ) {
            return encoder.encodeString(value.value)
        }
    }
}

When trying so serialize this object, this custom serializer never gets used. As a result, i get a json string containing the enum name, instead of the value, thus not conforming to my json schema.

0us avatar Feb 24 '21 12:02 0us

I figured out that kotlinx needs to be explicitly told to use the quicktype generated serialized. Otherwise, is generates it own, and uses that one instead.

So, a solution would be to change the @Serializable annotation of any class that has custom serializers to look like this:

@Serializable(with = MyClass.Companion::class)

0us avatar Feb 25 '21 12:02 0us

Kotlinx supports @SerialName for enums. No need to generate custom serializers anymore. It can be just

@Serializable
enum class MessageFunction(val value: String) {
    @SerialName("AUTP")
    Autp("AUTP"),

    @SerialName("AUTQ")
    Autq("AUTQ")
}

DmitriyZaitsev avatar May 25 '21 10:05 DmitriyZaitsev

Good afternoon, Initial testing with a simple change to Kotlin.ts has borne some fruit in this matter.

Including a SerialName in the enum definitions has allowed all tests to pass in a piece of code I have that has a problem that originates with this issue.

image

kevinvandenbreemen avatar May 12 '22 18:05 kevinvandenbreemen