Search code examples
kotlinswaggerkotlinx.serialization

Serialize Enum as an Integer


I have generated some models using the Open API tool on one of our backend APIs with Swagger. I got the following as the enum definition:

@Serializable
enum class ClientBackgroundState(val value: kotlin.Int) {

    @SerialName(value = "0")
    NONE(0),

    @SerialName(value = "1")
    FOREGROUND(1),

    @SerialName(value = "2")
    BACKGROUND(2);
}

When I use Kotlin Serializer, it serializes the above type into a String like "FOREGROUND" and the Backend API explodes because it wants an Integer.

Is there a way to configure the serializer to convert this enum to an Integer?


Solution

  • I have this solution. Create a "simple" base class:

    open class EnumAsIntSerializer<T:Enum<*>>(
        serialName: String,
        val serialize: (v: T) -> Int,
        val deserialize: (v: Int) -> T
    ) : KSerializer<T> {
        override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(serialName, PrimitiveKind.INT)
    
        override fun serialize(encoder: Encoder, value: T) {
            encoder.encodeInt(serialize(value))
        }
    
        override fun deserialize(decoder: Decoder): T {
            val v = decoder.decodeInt()
            return deserialize(v)
        }
    }
    

    And use it this way per an enum type:

    private class PartOfSpeechSerializer: EnumAsIntSerializer<PartOfSpeech>(
        "PartOfSpeech",
        { it.value },
        { v -> PartOfSpeech.values().first { it.value == v } }
    )
    
    @Serializable(with = PartOfSpeechSerializer::class)
    enum class PartOfSpeech(val value: Int) {
        Undefined(0),
        Noun(1),
        Verb(2),
        Adjective(3),
        Adverb(4),
        Pronoun(5),
        Preposition(6),
        Conjunction(7),
        Interjection(8)
    }