Несколько форм в Kotlin
Одно поле может хранить разные варианты данных:
успех с числом или ошибка с текстом. Ключевое слово sealed
интерфейс или класс перечисляет допустимые формы,
а @Serializable на базе и на каждой
ветке включает полиморфный кодек.
Для JSON библиотека добавляет служебный ключ
type - дискриминатор, по которому при
чтении выбирают конкретный data class.
Имя варианта задают через @SerialName:
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
sealed interface PayReply
@Serializable
@SerialName("paid")
data class Paid(val amount: Int) : PayReply
@Serializable
@SerialName("declined")
data class Declined(val reason: String) : PayReply
Запись значения типа PayReply включает
"type":"paid" или "type":"declined"
рядом с полями варианта:
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@Serializable
sealed interface PayReply
@Serializable
@SerialName("paid")
data class Paid(val amount: Int) : PayReply
@Serializable
@SerialName("declined")
data class Declined(val reason: String) : PayReply
fun main() {
val ok: PayReply = Paid(900)
val text = Json.encodeToString(ok)
println(text)
val back = Json.decodeFromString<PayReply>(text)
println(back)
}
После разбора статический тип снова PayReply,
а фактическая форма определяется при проверке
ветки when. Без @SerialName
в текст попало бы длинное системное имя класса,
а не короткая метка протокола.
Опишите @Serializable sealed
InboxEvent с вариантами Opened
(поле msgId, имя "opened")
и Archived (поле folder,
имя "archived"). Запишите событие
Opened с идентификатором 7
в JSON и выведите строку.
Разберите текст
{"type":"archived","folder":"2024"}
в InboxEvent и выведите имя папки
из восстановленного варианта.