kotlinx.serialization: модели и JSON
Как превратить Kotlin-классы в JSON и обратно одинаково на Android и iOS, без рефлексии.
kotlinx.serialization — мультиплатформенная библиотека сериализации, генерирующая код сериализаторов на этапе компиляции по аннотации
@Serializable, без рефлексии в рантайме.
Почему не Gson/Moshi
Привычные на Android Gson и Moshi опираются на рефлексию JVM — её нет на Kotlin/Native. Поэтому в KMP используют kotlinx.serialization: компиляторный плагин генерирует сериализатор для каждого @Serializable-класса прямо в код. Это работает на всех целях и быстрее рефлексии.
Объявление модели
// commonMain
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerialName
@Serializable
data class OrderDto(
val id: Long,
@SerialName("total_amount") val totalAmount: Double,
val items: List<ItemDto>
)
@Serializable
data class ItemDto(val name: String, val qty: Int)@SerialName сопоставляет имя поля Kotlin с именем в JSON (snake_case в API против camelCase в коде).
Парсинг и сборка JSON
// commonMain
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
val json = Json { ignoreUnknownKeys = true }
val order: OrderDto = json.decodeFromString(rawJson)
val back: String = json.encodeToString(order)Флаг ignoreUnknownKeys важен на проде: API добавит новое поле — клиент не упадёт.
Подключение плагина
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization") version "2.0.0"
}Как работает под капотом
Плагин сериализации на этапе компиляции для каждого @Serializable-класса генерирует объект-сериализатор: код, который читает/пишет поля по порядку, зная их типы. Никакого анализа классов в рантайме — всё известно заранее. Поэтому одна и та же модель сериализуется идентично на Android и iOS, и нет проблемы «на iOS рефлексия не работает». Это же объясняет требование @Serializable: без аннотации плагину нечего генерировать, и компиляция выдаст ошибку при попытке сериализовать такой тип.
Частые ошибки
Забыть @Serializable на вложенной модели (ItemDto) — компилятор пожалуется, что для типа нет сериализатора. Аннотировать нужно все участвующие классы. Вторая ошибка — не выставить ignoreUnknownKeys и ловить краши при эволюции API. Третья — путать DTO (модели API) с доменными моделями; держите их раздельно и маппите, иначе формат бэкенда протечёт во всё приложение.
Итоги
kotlinx.serializationработает без рефлексии — пригодна для Native.- Сериализатор генерируется на компиляции по
@Serializable. @SerialNameмостит имена JSON и Kotlin;ignoreUnknownKeysспасает при росте API.- Все участвующие классы должны быть аннотированы.