1

I am using kotlinx.serialisation and had a question.

I have JSON like this:

{ 
    "state": "bad"
}

state can return bad|good|near_good

My State data class looks like this:

@Serializable
internal enum class State {
    @SerialName("good") GOOD,
    @SerialName("bad") BAD,
    @SerialName("near_good") NEAR_GOOD
}

Is it possible to have the enum names remain all caps like this, while parsing the json value that is returned? Right now when I test this, the parsed json data returns as GOOD|BAD|NEAR_GOOD, because the enum name is uppercase. Hopefully the question makes sense. Appreciate any answers.

EDIT (Updated for clarity)

Right now I have a test that checks: assert(state.name == "bad") This fails because with the way I mentioned it above (@SerialName("bad") BAD), the state.name is equal to 'BAD'. I want the enum name to be uppercase, as per enum naming convention, but I want the value to be lowercase as per the JSON. I can fix the failing test by changing it to be

@SerialName("bad") bad

I'm not sure if it is possible or maybe I am doing something in the wrong way, but I hope this clarifies.

Thanks!

Ayohaych
  • 5,099
  • 7
  • 29
  • 51
  • 2
    I don't understand what part of the current behaviour doesn't fullfil your requirements – Joffrey Jan 16 '23 at 15:39
  • 2
    *the parsed json data returns as GOOD|BAD|NEAR_GOOD* - what does that mean? The parsed JSON data is an enum value, there is no notion of uppercase or lowercase, as those are objects. If you print them as strings, they will be uppercase by default, but that's independent from Kotlinx Serialization or even JSON parsing in general – Joffrey Jan 16 '23 at 15:41
  • 1
    *Is it possible to have the enum names remain all caps like this* - do you mean you want to be able to parse values in uppercase from other JSONs than the example one? Do you want to support JSONs with both lowercase and uppercase values? – Joffrey Jan 16 '23 at 15:44
  • @Joffrey thanks for the replies, I have updated the OP with further information. Maybe I am understanding something incorrectly, maybe what I am asking is not possible but I hope it makes more sense what I am trying to achieve – Ayohaych Jan 16 '23 at 16:03
  • 1
    *Right now I have a test that checks: assert(state.name == "bad") This fails* - that was the crucial piece of info I was missing :) – Joffrey Jan 16 '23 at 16:44

2 Answers2

2

I guess the problem is your test. It's not very robust to check for string equality. You have powerful compile-time guarantees with enums, so I would suggest to just compare enum values, not strings:

assert(state == State.BAD)

If you're trying to test the serial name of the enum value, then... don't? That's the job of Kotlinx Serialization's tests to verify that the annotations work correctly.

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • Thank you for clarifying. I guess I got confused as I saw that when I debugged, state.name was 'BAD' so I thought that if in the future we needed to parse or send this data to the server, and they expected lowercase 'bad', it might have some issue, as we would be sending 'BAD' instead. – Ayohaych Jan 16 '23 at 17:00
  • 1
    `@SerialName` works both ways, so if you serialize this value, it will be send according to the annotation - lowercase. – Joffrey Jan 16 '23 at 17:03
1

name is the wrong property to use for this purpose. It is documented as:

Returns the name of this enum constant, exactly as declared in its enum declaration.

What you could possibly do instead is to define a property (and, if you like, toString) for your enum class as follows:

val serialName =
    declaringJavaClass.getField(name)
        .getAnnotation(SerialName::class.java)
        .value

// optionally set toString
override fun toString() = serialName

And then you can print it like this: println(state.serialName)

Or like this: println(state)

But the real question is:

Why do you want to do that?

The whole point of the SerialName name annotation is to parse the serialized value to your enum variable, and to encode your enum variable to the serialized value. The value of your enum variable itself is independent from the serialized value and remains an object (State.BAD etc) rather than a string.

k314159
  • 5,051
  • 10
  • 32
  • Thank you for explaining and adding further information. As I mentioned below, I was under the assumption that the actual string value was being set to BAD, as it is what I saw when I debugged – Ayohaych Jan 16 '23 at 17:00