Я использую 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
Я не уверен, возможно ли это, или, может быть, я делаю что-то не так, но я надеюсь, что это прояснит.
Спасибо!
проанализированные данные json возвращаются как GOOD|BAD|NEAR_GOOD – что это значит? Проанализированные данные JSON представляют собой значение перечисления, нет понятия верхнего или нижнего регистра, поскольку это объекты. Если вы печатаете их в виде строк, по умолчанию они будут в верхнем регистре, но это не зависит от сериализации Kotlinx или даже от разбора JSON в целом.
Возможно ли, чтобы имена перечислений оставались такими же заглавными? Вы имеете в виду, что хотите иметь возможность анализировать значения в верхнем регистре из других JSON, а не из примера? Вы хотите поддерживать JSON как со значениями нижнего, так и с верхнего регистра?
@Joffrey, спасибо за ответы, я обновил OP дополнительной информацией. Может быть, я что-то неправильно понимаю, может быть, то, что я прошу, невозможно, но я надеюсь, что это имеет больше смысла, чего я пытаюсь достичь
Прямо сейчас у меня есть тест, который проверяет: assert(state.name == "bad") Это не удается - это была важная часть информации, которую мне не хватало :)
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, поскольку это то, что я видел при отладке.
Я думаю, проблема в вашем тесте. Не очень надежно проверять равенство строк. У вас есть мощные гарантии времени компиляции с перечислениями, поэтому я бы предложил просто сравнивать значения перечислений, а не строки:
assert(state == State.BAD)
Если вы пытаетесь проверить серийное имя значения перечисления, то... нет? Это задача тестов Kotlinx Serialization, чтобы убедиться, что аннотации работают правильно.
Спасибо за уточнение. Думаю, я запутался, когда увидел, что при отладке state.name было «ПЛОХОЕ», поэтому я подумал, что если в будущем нам нужно будет проанализировать или отправить эти данные на сервер, а они ожидали «плохой» в нижнем регистре, это может быть есть какая-то проблема, так как вместо этого мы будем отправлять «ПЛОХОЕ».
@SerialName работает в обе стороны, поэтому, если вы сериализуете это значение, оно будет отправлено в соответствии с аннотацией — в нижнем регистре.
Я не понимаю, какая часть текущего поведения не соответствует вашим требованиям