Spec-Zone.ru › Kotlin 2

Сериализация классов

Аннотация @Serializable включает сериализацию по умолчанию всех свойств класса с полями хранения. Вы можете настроить это поведение в соответствии со своими потребностями. На этой странице рассматриваются различные способы сериализации: вы узнаете, как указать, какие свойства сериализуются, и как управлять процессом сериализации.

Перед началом убедитесь, что вы подключили необходимые зависимости библиотеки.

Аннотация @Serializable

Аннотация @Serializable включает автоматическую сериализацию свойств класса, позволяя преобразовывать класс в такие форматы, как JSON, и обратно.

В Kotlin сериализуются только свойства с полями хранения:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
class Project(
    // Property with a backing field – serialized
    var name: String
) {
    // Property with a backing field – serialized
    var stars: Int = 0

    // Getter-only property without a backing field - not serialized
    val path: String
        get() = "kotlin/$name"

    // Delegated property - not serialized
    var id by ::name
}

fun main() {
    val data = Project("kotlinx.serialization").apply { stars = 9000 }
    // Prints only the name and the stars properties
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization","stars":9000}
}
//sampleEnd

Сериализация ссылок на классы

Классы с аннотацией @Serializable могут содержать свойства, ссылающиеся на другие классы. Эти классы также должны иметь аннотацию @Serializable. При кодировании в JSON это приводит к появлению вложенного объекта JSON:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// The owner property references another serializable class User
class Project(val name: String, val owner: User)

// The referenced class must also be annotated with @Serializable
@Serializable
class User(val name: String)

fun main() {
    val owner = User("kotlin")
    val data = Project("kotlinx.serialization", owner)
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization","owner":{"name":"kotlin"}}
}
//sampleEnd

Чтобы ссылаться на несериализуемые классы, пометьте соответствующие свойства аннотацией @Transient или предоставьте для них собственный сериализатор.

Сериализация повторяющихся ссылок на объекты

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

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
class Project(val name: String, val owner: User, val maintainer: User)

@Serializable
class User(val name: String)

fun main() {
    val owner = User("kotlin")
    // References owner twice
    val data = Project("kotlinx.serialization", owner, owner)
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization","owner":{"name":"kotlin"},"maintainer":{"name":"kotlin"}}
}
//sampleEnd

Попытка сериализовать циклическую структуру приводит к переполнению стека. Чтобы исключить ссылки из сериализации, используйте аннотацию @Transient.

Сериализация обобщённых классов

Обобщённые классы в Kotlin поддерживают полиморфизм типов, который сериализация Kotlin обеспечивает во время компиляции. Например, рассмотрим обобщённый сериализуемый класс Payload<T>:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// The Payload<T> class can be used with built-in types like Int
// or with @Serializable user-defined types like Repository
class Payload<T>(val value: T)

@Serializable
data class Repository(val name: String, val language: String)

@Serializable
class BackupData(
    val issueCount: Payload<Int>,
    val mainRepo: Payload<Repository>
)

fun main() {
    val backup = BackupData(
        Payload(42),
        Payload(Repository("kotlinx.serialization", "Kotlin"))
    )
    println(Json.encodeToString(backup))
    // {"issueCount":{"value":42},"mainRepo":{"value":{"name":"kotlinx.serialization","language":"Kotlin"}}}
}
//sampleEnd

При сериализации обобщённого класса, например Box<T>, результат в формате JSON зависит от фактического типа, указанного для T во время компиляции. Если этот тип не сериализуем, возникает ошибка компиляции.

Необязательные свойства

Свойства со значениями по умолчанию являются необязательными при десериализации и могут пропускаться при сериализации, если формат настроен соответствующим образом. Например, конфигурация JSON по умолчанию пропускает кодирование значений по умолчанию.

Задание значений по умолчанию для необязательных свойств

В Kotlin десериализовать объект можно только в том случае, если во входных данных присутствуют все его свойства. Чтобы сделать свойство необязательным при сериализации, задайте значение по умолчанию, которое будет использоваться, если во входных данных значение не указано:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// Sets a default value for the optional language property
data class Project(val name: String, val language: String = "Kotlin")

fun main() {
    val data = Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization"}
    """)
    println(data)
    // Project(name=kotlinx.serialization, language=Kotlin)
}
//sampleEnd

Сериализация свойств, допускающих значение null

Сериализация Kotlin изначально поддерживает свойства, допускающие значение null. Как и другие значения по умолчанию, значения null не кодируются в выводе JSON:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// Defines a class with the renamedTo nullable property that has a null default value
class Project(val name: String, val renamedTo: String? = null)

fun main() {
    val data = Project("kotlinx.serialization")
    // The renamedTo property isn't encoded because its value is null
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization"}
}
//sampleEnd

Кроме того, при десериализации строго соблюдается безопасность null в Kotlin. Если объект JSON содержит значение null для свойства, не допускающего значение null, возникает исключение, даже если у свойства есть значение по умолчанию:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
data class Project(val name: String, val language: String = "Kotlin")

fun main() {
    val data = Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":null}
    """)
    println(data)
    // JsonDecodingException
}
//sampleEnd

Если вам нужно обрабатывать значения null из JSON сторонних источников, вы можете преобразовывать их в значение по умолчанию.

Вы также можете исключить явные значения null из закодированного JSON с помощью свойства explicitNulls.

Инициализаторы необязательных свойств

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

Пример:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
fun computeLanguage(): String {
    println("Computing")
    return "Kotlin"
}

@Serializable
// Skips the initializer if language is in the input
data class Project(val name: String, val language: String = computeLanguage())

fun main() {
    val data = Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":"Java"}
    """)
    println(data)
    // Project(name=kotlinx.serialization, language=Java)
}
//sampleEnd

В этом примере, поскольку во входных данных указано свойство language, строка Computing не выводится.

Управление сериализацией свойств со значениями по умолчанию с помощью @EncodeDefault

По умолчанию при сериализации в JSON исключаются свойства со значениями по умолчанию. Это уменьшает размер сериализованных данных и позволяет избежать лишнего визуального шума.

В следующем примере свойство language исключается из вывода, поскольку его значение совпадает со значением по умолчанию:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
data class Project(val name: String, val language: String = "Kotlin")

fun main() {
    val data = Project("kotlinx.serialization")
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization"}
}
//sampleEnd

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

Чтобы всегда сериализовать свойство независимо от его значения и настроек формата, используйте аннотацию @EncodeDefault. В качестве альтернативы можно изменить это поведение, задав параметр EncodeDefault.Mode.

Рассмотрим пример, в котором свойство language всегда включается в сериализованный результат, а свойство projects исключается, если оно представляет собой пустой список:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import kotlinx.serialization.EncodeDefault.Mode.NEVER

//sampleStart
@Serializable
data class Project(
    val name: String,
    // Always includes the language property in the serialized output
    // even if it has the default value "Kotlin"
    @EncodeDefault val language: String = "Kotlin"
)

@Serializable
data class User(
    val name: String,
    // Excludes projects when it's an empty list, even if it has a default value
    @EncodeDefault(NEVER) val projects: List<Project> = emptyList()
)

fun main() {
    val adminUser = User("Alice", listOf(Project("kotlinx.serialization")))
    val guestUser = User("Bob")
    // Serializes projects because it contains a value
    // language is always serialized
    println(Json.encodeToString(adminUser))
    // {"name":"Alice","projects":[{"name":"kotlinx.serialization","language":"Kotlin"}]}

    // Excludes projects because it's an empty list
    // and EncodeDefault.Mode is set to NEVER, so it's not serialized
    println(Json.encodeToString(guestUser))
    // {"name":"Bob"}
}
//sampleEnd

Обязательные свойства с аннотацией @Required

Пометьте свойство аннотацией @Required, чтобы сделать его обязательным во входных данных. Это гарантирует, что свойство будет присутствовать во входных данных, даже если у него есть значение по умолчанию:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import kotlinx.serialization.Required

//sampleStart
@Serializable
// Marks the language property as required
data class Project(val name: String, @Required val language: String = "Kotlin")

fun main() {
    val data = Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization"}
    """)
    println(data)
    // MissingFieldException
}
//sampleEnd

Настройка сериализации классов

Сериализация Kotlin предоставляет несколько способов изменить сериализацию классов. В этом разделе описываются способы настройки имён свойств, управления включением свойств и многое другое.

Настройка сериализуемых имён

По умолчанию имена свойств в результате сериализации, например в JSON, совпадают с их именами в исходном коде.

Вы можете настроить эти имена, называемые сериализуемыми именами, с помощью аннотации @SerialName. Используйте её, чтобы сделать имя свойства в сериализованном результате более понятным:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// Changes the lang property to language using @SerialName
class Project(val name: String, @SerialName("language") val lang: String)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin")
    // Prints the more descriptive property name in the JSON output
    println(Json.encodeToString(data))
    // {"name":"kotlinx.serialization","language":"Kotlin"}
}
//sampleEnd

Определение свойств конструктора для сериализации

Класс с аннотацией @Serializable должен объявлять все параметры первичного конструктора в качестве свойств.

Если перед присваиванием значений свойствам необходимо выполнить дополнительную логику инициализации, используйте вторичный конструктор. Первичный конструктор может оставаться private и отвечать за инициализацию свойств.

В следующем примере вторичный конструктор разбирает строку на два значения, которые затем передаются первичному конструктору для сериализации:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
class Project private constructor(val owner: String, val name: String) {
    // Creates a Project object using a path string
    constructor(path: String) : this(
        owner = path.substringBefore('/'),
        name = path.substringAfter('/')
    )

    val path: String
        get() = "$owner/$name"
}
fun main() {
    println(Json.encodeToString(Project("kotlin/kotlinx.serialization")))
    // {"owner":"kotlin","name":"kotlinx.serialization"}
}
//sampleEnd

Проверка данных в первичном конструкторе

После десериализации плагин kotlinx.serialization выполняет блоки инициализации класса так же, как при создании экземпляра. Это позволяет проверять параметры конструктора и отклонять недопустимые данные во время десериализации.

Пример:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.json.*

//sampleStart
@Serializable
class Project(val name: String) {
    // Validates that the name is not empty
    init {
        require(name.isNotEmpty()) { "name cannot be empty" }
    }
}

fun main() {
    val data = Json.decodeFromString<Project>("""
        {"name":""}
    """)
    println(data)
    // Exception in thread "main" java.lang.IllegalArgumentException: name cannot be empty
}
//sampleEnd

Исключение свойств с помощью аннотации @Transient

Свойство можно исключить из сериализации с помощью аннотации @Transient. У временных свойств должно быть значение по умолчанию.

Если явно указать во входных данных значение временного свойства, даже совпадающее со значением по умолчанию, будет выброшено исключение JsonDecodingException:

// Imports declarations from the serialization library
import kotlinx.serialization.*
import kotlinx.serialization.Transient
import kotlinx.serialization.json.*

//sampleStart
@Serializable
// Excludes the language property from serialization
data class Project(val name: String, @Transient val language: String = "Kotlin")

fun main() {
    // Throws an exception even though input matches the default value
    val data = Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":"Kotlin"}
    """)
    println(data)
    // JsonDecodingException
}
//sampleEnd

Чтобы избежать исключений из-за неизвестных ключей в JSON, в том числе помеченных аннотацией @Transient, включите свойство конфигурации ignoreUnknownKeys. Дополнительную информацию см. в разделе Игнорирование неизвестных ключей.

Что дальше

  • Узнайте о более сложных сценариях сериализации JSON в обзоре сериализации JSON.

  • Узнайте, как получать сгенерированные сериализаторы, создавать собственные сериализаторы и применять их, в разделе Создание и использование сериализаторов.

16 июня 2026 г.
Сериализация встроенных типовОбзор сериализации JSON

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/serialization-customization-options.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API