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

How to serialize enum to actual json number

Open AngryGami opened this issue 1 year ago • 1 comments

@Serializable
enum class TestEnum(val value: Int) {
    @SerialName(value = "1")
    V1(1),

    @SerialName(value = "2")
    V2(2);

}

fun main() {
    val json = Json.encodeToString(listOf(TestEnum.V1, TestEnum.V2))
    println(json)
}

Code above prints:

["1","2"]

How to make it print:

[1,2]

I.e. use proper json number as enum encoded value?

AngryGami avatar Apr 10 '24 12:04 AngryGami

As a workaround you may have to implement a customized serializer

iseki0 avatar Apr 14 '24 18:04 iseki0

You can use enumAsOrdinalSerializer from my complementary library if you'd like. Or just yank code from there to get a starting point. Note that it uses the ordinal value for the enum entries, so V1 in your example would be 0

Kantis avatar May 08 '24 13:05 Kantis

@Kantis thanks, I've already made my own custom (de)serializer, though I'll take a look at your solution.

AngryGami avatar May 08 '24 14:05 AngryGami

Note that ordinal will differ from val value: Int in your case.

sandwwraith avatar May 08 '24 15:05 sandwwraith

@sandwwraith Yes, I know And I would still prefer to have control over this via some annotation or parameter instead of writing custom serializer

AngryGami avatar May 08 '24 16:05 AngryGami

And I would still prefer to have control over this via some annotation or parameter instead of writing custom serializer

I don't think that is really possible at the moment. However it is certainly possible to have "canned" serializers that you just apply on a type. It would be interesting though to have an additional parameter to SerializationStrategy.encode and DeserializationStrategy.decode` that passes along the element annotations to the serializer. That would allow customization of such a serializer to work in a platform independent way (where annotations aren't available on all platforms).

There is a bit of a challenge in implementing this. It is possible to implement the new function as a default interface implementation that passes to the original function. This retains compatibility. This however means that for implementation of the new interface the old functions will also need to be implemented, perhaps this is still better though than having both functions default implemented and referring to each other (which would also be binary compatible, but be poor API design).

pdvrieze avatar May 08 '24 18:05 pdvrieze