kotlinx.serialization — JetBrains tomonidan Kotlin obyektlarini JSON, ProtoBuf, CBOR va boshqa formatlarga refleksiyasiz aylantirish uchun koʻp platformali kutubxona. Gson va Moshidan farqli oʻlaroq, u @Serializable annotatsiyasi orqali kompilatsiya bosqichida serializator kodini yaratadi, bu esa yuqori samaradorlik va tip xavfsizligini taʻminlaydi. GitHub Kotlin/kotlinx.serialization maʻlumotlariga koʻra, kutubxona Kotlin/JVM, Kotlin/Native, Kotlin/JS va Kotlin/Wasm-ni qoʻlab-quvvatlaydi.
Asosiy
kotlinx.serialization — JetBrains tomonidan rasmiy Kotlin ekotizimining bir qismi sifatida ishlab chiqilgan Kotlin uchun oʻrnatilgan serializatsiya kutubxonasi. Uning uchinchi tomon echimlaridan (Gson, Moshi, Jackson) asosiy farqi shundaki, u ishlash vaqtida refleksiyadan foydalanmaydi. Buning oʻrniga serializator kodi Kotlin Symbol Processing (KSP) yoki Kotlin Compiler Plugin yordamida kompilatsiya bosqichida yaratiladi. Bu Gson bilan solishtirganda 3-5 baravar samaradorlik oshishini va tip xavfsizligini taʻminlaydi.
Kutubxona rasmiy ravishda toʻrtta formatni qoʻlab-quvvatlaydi: JSON (kotlinx-serialization-json moduli orqali), ProtoBuf (kotlinx-serialization-protobuf), CBOR (kotlinx-serialization-cbor) va HOCON (kotlinx-serialization-hocon). Formatlar build.gradle.kts da alohida bogʻliqliklar sifatida qoʻshiladi, bu esa loyihaga keraksiz kutubxonalarni tortmaslikka imkon beradi. Har bir format uchun oʻz konfiguratsiya parametrlari toʻplami mavjud.
Koʻp platformalilik — kutubxonaning asosiy xususiyati. @Serializable bilan bir xil sinf barcha maqsadli platformalarda ishlaydi: JVM (Android, Backend), Native (iOS), JS (Web, React) va Wasm (WebAssembly). Dasturchi har bir platforma uchun turli xil serializatsiya implementatsiyalarini yozishi shart emas — kod yagona boʻlib qoladi. Bu, ayniqsa, umumiy kod Android va iOS oʻrtasida taqsimlanadigan Kotlin Multiplatform Mobile (KMM) loyihalarida qimmatlidir.
Kod yaratilishi kotlinx.serialization da uch bosqichda amalga oshiriladi. Birinchi bosqichda Kotlin kompilatori sinfda @Serializable annotatsiyasini aniqlaydi va uni Kotlin Symbol Processing (KSP) plagiga uzatadi. Ikkinchi bosqichda KSP KSerializer interfeysini amalga oshiradigan serializator obyektini yaratadi. Uchinchi bosqichda yaratilgan kod loyihaning manba kodi bilan birga kompilatsiya qilinadi. Natijada, bu bosqichlarning hech biri dastur ishlashi vaqtida bajarilmaydi.
Yaratilgan serializator sinf maydonlari bilan toʻgʻridan-toʻgʻri ularning getter va setterlari orqali, refleksiyasiz ishlaydi. Bu shuni anglatadiki, private modifikatoriga ega maydonlar ham @Serializable bilan belgilangan boʻlsa, serializatsiya qilinadi. Ushbu yondashuvning samaradorligi qoʻlda serializatsiyaga yaqin: oddiy sinflar (5-10 maydon) uchun serializatsiya vaqti 10-50 mikrosekund, murakkab obyekt graflari uchun 1000 obyektga 200 mikrosekundgacha.
Android yoki Kotlin/JVM loyihasida kutubxonani ulash uchun build.gradle.kts fayliga plagin va bogʻliqliklarni qoʻshish kerak. Kotlin versiyasiga mos keladigan org.jetbrains.kotlin.plugin.serialization plagini kod yaratilishini faollashtiradi. kotlinx-serialization-json kutubxonasi dependencies boʻlimida Kotlin versiyasiga bogʻliq boʻlmagan versiya bilan qoʻshiladi.
// build.gradle.kts — kotlinx.serialization ulanishi
plugins {
val kotlinVersion = "2.1.0"
kotlin("jvm") version kotlinVersion
kotlin("plugin.serialization") version kotlinVersion
}
dependencies {
// Asosiy serializatsiya moduli
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
// Qoʻshimcha formatlar
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-cbor:1.7.3")
}
JSON — kotlinx.serialization da eng mashhur format. Obyektni serializatsiya qilish uchun data class ga @Serializable annotatsiyasini qoʻyish va Json.encodeToString() ni chaqirish kifoya. Deserializatsiya uchun — Json.decodeFromString() turni koʻrsatgan holda. Kutubxona avtomatik ravishda null maydonlarni, roʻyxatlarni, ichki obyektlarni va enumlarni boshqaradi. Sinfning barcha maydonlari boshqacha koʻrsatilmagan boʻlsa, majburiydir.
JSON konfiguratsiyasi Json {} builder orqali amalga oshiriladi. Konstruktorga deserializatsiya vaqtida nomaʻlum maydonlarni oʻtkazib yuborish uchun ignoreUnknownKeys = true, formatlangan chiqish uchun prettyPrint = true, notoʻgʻri qiymatlarni standart qiymatlarga aylantirish uchun coerceInputValues = true berilishi mumkin. Shuningdek, encodeDefaults (standart qiymatli maydonlarni serializatsiya qilish) va classDiscriminator (polimorf serializatsiya uchun maydon nomi) sozlamalari mavjud.
// JSON serializatsiyasi va deserializatsiyasi misoli
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
@Serializable
data class Project(
val name: String,
val stars: Int,
val isActive: Boolean = true,
val languages: List<String> = emptyList()
)
fun main() {
val project = Project(
name = "kotlinx.serialization",
stars = 7200,
languages = listOf("Kotlin", "Java")
)
// JSON ga prettyPrint bilan serializatsiya
val json = Json { prettyPrint = true }
val jsonString = json.encodeToString(project)
println(jsonString)
/*
{
"name": "kotlinx.serialization",
"stars": 7200,
"isActive": true,
"languages": ["Kotlin", "Java"]
}
*/
// JSON dan deserializatsiya
val decoded = json.decodeFromString<Project>(jsonString)
println(decoded.name) // kotlinx.serialization
}
Misol asosiy tsiklni — serializatsiya va deserializatsiyani koʻrsatadi. @Serializable annotatsiyasiga ega Project data class avtomatik ravishda encodeToString va decodeFromString oladi. isActive maydoni standart qiymat true ga ega — agar bu maydon JSON da boʻlmasa, standart qiymat ishlatiladi. Agar ignoreUnknownKeys = true boʻlmagan holda JSON da nomaʻlum maydonlar kelsa, SerializationException istisnosi tashlanadi.
Sealed class — kotlinx.serialization ning eng kuchli foydalanish holatlaridan biri. Kutubxona qoʻshimcha konfiguratsiyasiz sealed class iyerarxiyalari uchun polimorf serializatsiyani qoʻlab-quvvatlaydi: sealed class va uning barcha vorislarini @Serializable bilan belgilash kifoya. Serializatsiya vaqtida „type” maydoni (classDiscriminator orqali sozlanishi mumkin) qoʻshiladi, uning asosida deserializatsiya vaqtida aniq tur aniqlanadi.
// Sealed class polimorf serializatsiyasi
@Serializable
sealed class Response
@Serializable
data class Success(val data: String) : Response()
@Serializable
data class Error(val code: Int, val message: String) : Response()
fun main() {
val json = Json { classDiscriminator = "result_type" }
val responses: List<Response> = listOf(
Success(data = "Data loaded"),
Error(code = 404, message = "Not found")
)
val jsonString = json.encodeToString(responses)
println(jsonString)
/*
[
{"result_type":"Success","data":"Data loaded"},
{"result_type":"Error","code":404,"message":"Not found"}
]
*/
val decoded = json.decodeFromString<List<Response>>(jsonString)
when (val first = decoded[0]) {
is Success -> println("Success: ${first.data}")
is Error -> println("Error: ${first.code}")
}
}
Sealed class polimorf serializatsiyasi, ayniqsa, server turli xil javob turlarini qaytaradigan API mijozlarida foydalidir. kotlinx.serialization boʻlmagan holda, diskriminator maydoni boʻyicha when bilan qoʻlda deserializator yozish kerak boʻlardi. Kutubxona bilan bu bitta annotatsiya bilan amalga oshiriladi. classDiscriminator marker maydoni nomini (standart „type”) server kutgan istalgan qiymatga oʻzgartirishga imkon beradi.
Kutubxona serializatsiyani nozik sozlash uchun annotatsiyalar toʻplamini taqdim etadi. Asosiysi sinf uchun @Serializable. Qoʻshimchalar: JSON da maydon nomini belgilash uchun @SerialName (Kotlin nomidan farq qilsa), maydonni serializatsiyadan chiqarish uchun @Transient, JSON da majburiy boʻlgan maydon uchun @Required, standart qiymatli maydonni majburiy serializatsiya qilish uchun @EncodeDefault.
| Annotatsiya | Vazifa | Misol |
|---|---|---|
| @Serializable | Sinf uchun serializator yaratilishini faollashtiradi | @Serializable data class User |
| @SerialName | Maydonning formatdagi muqobil nomini belgilaydi | @SerialName(“user_name”) val name: String |
| @Transient | Maydonni serializatsiyadan chiqaradi | @Transient val cache: MutableMap |
| @Required | Maydon deserializatsiya vaqtida JSON da majburiy | @Required val id: String |
| @EncodeDefault | Maydonni hatto standart qiymat bilan ham serializatsiya qiladi | @EncodeDefault val type: Type = Type.A |
| @Serializer | Sinfga maxsus serializatorni biriktiradi | @Serializer(forClass = Date::class) |
@SerialName annotatsiyasi maydon nomlari snake_case, Kotlin uslubi esa camelCase boʻlgan API lar bilan ishlashda juda muhimdir. Masalan, server “user_id” yuboradi, Kotlin kodida esa userId ishlatiladi. @SerialName(“user_id”) bu muammoni qoʻshimcha mapperlarsiz hal qiladi. @Transient serverga yuborish shart boʻlmagan maydonlar uchun qulay — masalan, vaqtinchalik hisoblash qiymatlari yoki kesh.
Standart boʻyicha kotlinx.serialization da barcha maydonlar majburiydir. Agar maydon JSON da boʻlmasligi mumkin boʻlsa, uni nullable (String?) qilish yoki standart qiymat belgilash kerak (val name: String = “”). Biroq, maydon Kotlin da nullable emas, lekin API versiyalash tufayli JSON da boʻlmasligi mumkin boʻlgan holatlar mavjud. Bu holda @Required maydon yoʻq boʻlganda SerializationException tashlaydi, standart qiymat esa xatosiz default ni toʻldiradi.
KSerializer — kotlinx.serialization da barcha serializatorlar amalga oshiradigan interfeys. Agar standart kod yaratilishi mos kelmasa (masalan, Date, Bitmap yoki maxsus ikkilik format bilan ishlash uchun), oʻz serializatoringizni yozishingiz mumkin. Buning uchun serialize() va deserialize() metodlarini, shuningdek format sxemasi uchun descriptor — struktura tavsifini taqdim etish kerak.
Maxsus serializatorlar ikki usulda ulanadi: muayyan sinfga ulash uchun @Serializable(with = MySerializer::class) annotatsiyasi orqali yoki Json { serializersModule = ... } orqali global ravishda barcha tur namunalariga ulash. Ikkinchi usul oʻrnatilgan turlar (Date, UUID) uchun afzalroqdir, chunki har bir maydonda annotatsiya yozish shart emas.
// java.util.Date uchun maxsus serializator
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
object DateSerializer : KSerializer<Date> {
private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Date) {
encoder.encodeString(dateFormat.format(value))
}
override fun deserialize(decoder: Decoder): Date {
return dateFormat.parse(decoder.decodeString())
}
}
// Maxsus serializatordan foydalanish
@Serializable
data class Event(
val title: String,
@Serializable(with = DateSerializer::class)
val date: Date
)
fun main() {
val json = Json { prettyPrint = true }
val event = Event("Chiqarilish", Date())
println(json.encodeToString(event))
}
Misolda DateSerializer java.util.Date ni ISO 8601 qatoriga aylantiradi. Maxsus serializatorsiz kotlinx.serialization Date bilan ishlay olmaydi — bu Kotlin standart kutubxonasiga kirmaydigan turdir. Muayyan maydonda @Serializable(with = DateSerializer::class) serializatorni faqat shu maydon uchun ulaydi. Barcha Date larning global roʻyxatga olinishi uchun Json { serializersModule = SerializersModule { contextual(DateSerializer) } } dan foydalaning.
kotlinx.serialization faqat JSON bilan cheklanmaydi. Kutubxona toʻrtta oʻrnatilgan formatni qoʻlab-quvvatlaydi, har biri oʻz moduli va konfiguratsiyasiga ega. JSON (kotlinx-serialization-json) — universal, inson oʻqiy oladigan, REST API uchun mos. ProtoBuf (kotlinx-serialization-protobuf) — ikkilik, ixcham, majburiy sxema bilan, yuqori yuklangan mikroxizmatlar uchun. CBOR (kotlinx-serialization-cbor) — JSON ning ikkilik analogi, cheklangan trafikli IoT va mobil qurilmalar uchun qulay. HOCON (kotlinx-serialization-hocon) — TypeSafe Config bilan mos keladigan konfiguratsiya formati.
| Format | Modul | Tur | Sxema | Odatiy qoʻllanish |
|---|---|---|---|---|
| JSON | kotlinx-serialization-json | Matnli | Ixtiyoriy | REST API, maʻlumot saqlash |
| ProtoBuf | kotlinx-serialization-protobuf | Ikkilik | Majburiy (.proto) | Mikroxizmatlar, gRPC |
| CBOR | kotlinx-serialization-cbor | Ikkilik | Ixtiyoriy | IoT, mobil qurilmalar |
| HOCON | kotlinx-serialization-hocon | Matnli | Ixtiyoriy | Konfiguratsiya fayllari |
ProtoBuf .proto fayllarida sxema belgilashni talab qiladi, lekin kotlinx-serialization-protobuf Kotlin sinflarini toʻgʻridan-toʻgʻri @Serializable dan .proto siz yaratadi. Bu rivojlanishni soddalashtiradi: data class ni annotatsiya qilish va ProtoBuf.encodeToByteArray() dan foydalanish kifoya. CBOR, ayniqsa, NFC yoki BLE orqali ixcham ikkilik maʻlumotlarni uzatish kerak boʻlganda Android ramkasi uchun dolzarbdir. CBOR xabarining hajmi bir xil maʻlumotlar toʻplami bilan JSON dan oʻrta hisobda 20-30% kichikroq.
Mobil ilovada REST API uchun JSON maqbuldir — qoʻshimcha vositalarsiz sozlanadi, jurnallarda oʻqiladi va har qanday backend bilan mos keladi. Agar ilova mikroxizmatlar oʻrtasida katta hajmdagi maʻlumotlarni uzatsa (yuzlab megabayt) — ProtoBuf ikkilik kodlash tufayli tezlikni 5 baravargacha oshiradi. Sozlamalarni fayllarda saqlash uchun HOCON yoki JSON dan foydalaning. Qattiq trafik cheklovlari boʻlgan qurilmalar (IoT sensorlari) uchun — CBOR.
Birinchi xato — deserializatsiya vaqtida nomaʻlum kalitlarni eʻtiborsiz qoldirish. Agar server yangi maydon qoʻshgan boʻlsa va ignoreUnknownKeys = false boʻlsa, dastur SerializationException bilan ishdan chiqadi. Standart boʻyicha bu bayroq oʻchirilgan. Yechim: API oʻzgarishlariga chidamli boʻlish uchun ishlab chiqarish kodida har doim Json { ignoreUnknownKeys = true } ni oʻrnating.
Ikkinchi xato — data class da internal yoki private maydonlarni serializatsiya qilish. Kotlin data class da primary konstruktordagi barcha maydonlar standart boʻyicha serializatsiya qilinadi. Agar maydon maxfiy maʻlumotlarni oʻz ichiga olsa (parol, token), uni @Transient bilan belgilash yoki primary konstruktordan chiqarish kerak. @Transient maydonni JSON dan butunlay chiqarib tashlaydi, lekin konstruktorda xatoga olib kelishi mumkin — bunday maydonni @Transient bilan sinf tanasida belgilash yaxshiroqdir.
Uchinchi xato — sealed class siz polimorf serializatsiya. Agar sealed oʻrniga open class ishlatilsa, kotlinx.serialization serializersModule da barcha vorislarning aniq roʻyxatga olinishini talab qiladi. sealed class dan farqli oʻlaroq, kompilator barcha vorislarni biladi, open class esa ixtiyoriy kengaytirishga imkon beradi — kutubxona barcha pastki turlarni avtomatik aniqlay olmaydi. Roʻyxatga olish Json { serializersModule = SerializersModule { polymorphic(Base::class) { subclass(Derived::class) } } } orqali amalga oshiriladi.
kotlinx.serialization versiyasi Kotlin versiyasiga mos boʻlishi kerak. JetBrains moslik jadvalini eʻlon qiladi: kotlinx-serialization 1.6.x Kotlin 1.9.x bilan, 1.7.x Kotlin 2.0.x va 2.1.x bilan mos keladi. Versiyalarning mos kelmasligi „Symbol ‘serializer’ is missing” kabi tushunarsiz kompilatsiya xatolariga sabab boʻladi. Har doim joriy versiyani mavenCentral da yoki loyihaning GitHub repozitoriyasida tekshiring.
Tez-tez beriladigan savollar
kotlinx.serialization KSP orqali kompilatsiya vaqtida kod yaratishdan foydalanadi, Gson va Moshi esa ishlash vaqtida refleksiyadan foydalanadi. Bu samaradorlikda ustunlik (Gson dan 3-5 baravar tez) va tip xavfsizligini taʻminlaydi. Gson annotatsiyasiz istalgan maydonni serializatsiya qiladi, bu maʻlumot sizib chiqishiga olib kelishi mumkin. kotlinx.serialization aniq @Serializable annotatsiyasini talab qiladi, bu xavfsizroqdir. Moshi ham codegen ni qoʻlab-quvvatlaydi, lekin faqat JVM va Android uchun.
Ha, kotlinx.serialization JetBrainsning rasmiy koʻp platformali kutubxonasi. U Kotlin/JVM (Android, Backend), Kotlin/Native (iOS), Kotlin/JS (Web, React) va Kotlin/Wasm da ishlaydi. API barcha platformalar uchun yagonadir: @Serializable + Json.encodeToString() hamma joyda bir xil ishlaydi. iOS uchun qoʻshimcha sozlamalar talab qilinmaydi — Kotlin/Native serializatsiya qilingan kodni mahalliy ikkilik faylga kompilatsiya qiladi.
Nullable maydonlar (String?) JSON da qiymat boʻlmasa yoki null koʻrsatilsa, null sifatida deserializatsiya qilinadi. Standart qiymati boʻlmagan non-nullable maydonlar (String) uchun JSON da maydonning yoʻqligi SerializationException ga sabab boʻladi. Agar null qiymatlarning JSON ga tushishini istamasangiz, Json { encodeDefaults = false } ni sozlang. Bu default ga teng boʻlgan barcha maydonlarni (nullable uchun null ni oʻz ichiga olgan holda) chiqishdan chiqaradi.
@SerialName(“snake_case_name”) dan foydalaning nomi Kotlin formatidan farq qiladigan har bir maydonda. Shu bilan birga, Kotlin 2.0+ uchun Json { namingStrategy = JsonNamingStrategy.SnakeCase } mavjud — camelCase ↔ snake_case avtomatik konversiyasi. Bu sozlama barcha maydonlarga bir vaqtning oʻzida qoʻllaniladi. Qisman moslashtirish kerak boʻlsa, @SerialName ni global strategiya bilan birlashtiring.
Yoʻq, Flow va korutinlar toʻgʻridan-toʻgʻri serializatsiya qilinmaydi — ular asinxron bajarilishni ifodalaydi, maʻlumotni emas. Flow dan maʻlumot uzatish uchun uni korutinda .toList() orqali toʻplamga yigʻish va toʻplamni serializatsiya qilish kerak. Xuddi shunday, Job, Deferred yoki Continuation ni serializatsiya qilib boʻlmaydi. Faqat data class — xatti-harakat mantigʻi boʻlmagan maʻlumot modellarini serializatsiya qiling.
Xulosalar
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.