Сериализация Kotlin с помощью Enum (библиотека kotlinx.serialisation)

Я использую kotlinx.serialisation и у меня возник вопрос.

У меня JSON такой:

{ 
    "state": "bad"
}

состояние может возвращать плохое|хорошее|почти_хорошее

Мой класс данных State выглядит следующим образом:

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

Возможно ли, чтобы имена перечислений оставались такими же заглавными при анализе возвращаемого значения json? Прямо сейчас, когда я проверяю это, проанализированные данные json возвращаются как GOOD|BAD|NEAR_GOOD, потому что имя перечисления указано в верхнем регистре. Надеюсь, вопрос имеет смысл. Цените любые ответы.

РЕДАКТИРОВАТЬ (обновлено для ясности)

Прямо сейчас у меня есть тест, который проверяет: утверждать (state.name == "плохо") Это не удается, потому что, как я упомянул выше (@SerialName("bad") BAD), state.name равно 'BAD'. Я хочу, чтобы имя перечисления было в верхнем регистре в соответствии с соглашением об именовании перечисления, но я хочу, чтобы значение было в нижнем регистре в соответствии с JSON. Я могу исправить неудачный тест, изменив его на

@SerialName("bad") bad

Я не уверен, возможно ли это, или, может быть, я делаю что-то не так, но я надеюсь, что это прояснит.

Спасибо!

Я не понимаю, какая часть текущего поведения не соответствует вашим требованиям

Joffrey 16.01.2023 16:39

проанализированные данные json возвращаются как GOOD|BAD|NEAR_GOOD – что это значит? Проанализированные данные JSON представляют собой значение перечисления, нет понятия верхнего или нижнего регистра, поскольку это объекты. Если вы печатаете их в виде строк, по умолчанию они будут в верхнем регистре, но это не зависит от сериализации Kotlinx или даже от разбора JSON в целом.

Joffrey 16.01.2023 16:41

Возможно ли, чтобы имена перечислений оставались такими же заглавными? Вы имеете в виду, что хотите иметь возможность анализировать значения в верхнем регистре из других JSON, а не из примера? Вы хотите поддерживать JSON как со значениями нижнего, так и с верхнего регистра?

Joffrey 16.01.2023 16:44

@Joffrey, спасибо за ответы, я обновил OP дополнительной информацией. Может быть, я что-то неправильно понимаю, может быть, то, что я прошу, невозможно, но я надеюсь, что это имеет больше смысла, чего я пытаюсь достичь

Ayohaych 16.01.2023 17:03

Прямо сейчас у меня есть тест, который проверяет: assert(state.name == "bad") Это не удается - это была важная часть информации, которую мне не хватало :)

Joffrey 16.01.2023 17:44
1
5
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

name не подходит для этой цели. Это задокументировано как:

Возвращает имя этой константы перечисления точно так, как объявлено в ее объявлении перечисления.

Вместо этого вы могли бы определить свойство (и, если хотите, toString) для вашего класса enum следующим образом:

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

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

И тогда вы можете распечатать это так: println(state.serialName)

Или вот так: println(state)

Но настоящий вопрос:

Почему вы хотите это сделать?

Весь смысл аннотации имени SerialName заключается в том, чтобы проанализировать сериализованное значение в вашей переменной перечисления и закодировать вашу переменную перечисления в сериализованное значение. Значение вашей переменной перечисления не зависит от сериализованного значения и остается объектом (State.BAD и т. д.), а не строкой.

Спасибо за объяснение и добавление дополнительной информации. Как я упоминал ниже, я исходил из того, что фактическое строковое значение было установлено в BAD, поскольку это то, что я видел при отладке.

Ayohaych 16.01.2023 18:00
Ответ принят как подходящий

Я думаю, проблема в вашем тесте. Не очень надежно проверять равенство строк. У вас есть мощные гарантии времени компиляции с перечислениями, поэтому я бы предложил просто сравнивать значения перечислений, а не строки:

assert(state == State.BAD)

Если вы пытаетесь проверить серийное имя значения перечисления, то... нет? Это задача тестов Kotlinx Serialization, чтобы убедиться, что аннотации работают правильно.

Спасибо за уточнение. Думаю, я запутался, когда увидел, что при отладке state.name было «ПЛОХОЕ», поэтому я подумал, что если в будущем нам нужно будет проанализировать или отправить эти данные на сервер, а они ожидали «плохой» в нижнем регистре, это может быть есть какая-то проблема, так как вместо этого мы будем отправлять «ПЛОХОЕ».

Ayohaych 16.01.2023 18:00
@SerialName работает в обе стороны, поэтому, если вы сериализуете это значение, оно будет отправлено в соответствии с аннотацией — в нижнем регистре.
Joffrey 16.01.2023 18:03

Другие вопросы по теме