<commit_before><!--- TEST_NAME SerializersTest -->

# Serializers

This is the third chapter of the [Kotlin Serialization Guide](serialization-guide.md).
In this chapter we'll take a look at serializers in more detail and see how custom serializers can be written.

**Table of contents**

<!--- TOC -->

* [Introduction to serializers](#introduction-to-serializers)
  * [Plugin-generated serializer](#plugin-generated-serializer)
  * [Plugin-generated generic serializer](#plugin-generated-generic-serializer)
  * [Builtin primitive serializers](#builtin-primitive-serializers)
  * [Constructing collection serializers](#constructing-collection-serializers)
  * [Using top-level serializer function](#using-top-level-serializer-function)
* [Custom serializers](#custom-serializers)
  * [Primitive serializer](#primitive-serializer)
  * [Composite serializer via surrogate](#composite-serializer-via-surrogate)
  * [Hand-written composite serializer](#hand-written-composite-serializer)
  * [Sequential decoding protocol (experimental)](#sequential-decoding-protocol-experimental)
  * [Serializing 3rd party classes](#serializing-3rd-party-classes)
  * [Passing a serializer manually](#passing-a-serializer-manually)
  * [Specifying serializer on a property](#specifying-serializer-on-a-property)
  * [Specifying serializers for a file](#specifying-serializers-for-a-file)
  * [Custom serializers for a generic type](#custom-serializers-for-a-generic-type)
  * [Format-specific serializers](#format-specific-serializers)
* [Contextual serialization](#contextual-serialization)
  * [Serializers module](#serializers-module)
* [Deriving external serializer for another Kotlin class (experimental)](#deriving-external-serializer-for-another-kotlin-class-experimental)
  * [External serialization uses properties](#external-serialization-uses-properties)

<!--- END -->

## Introduction to serializers

Format, like JSON, controls the _encoding_ of an object into specific output bytes, but how the object is decomposed 
into its constituent properties is controlled by a _serializer_. So far, we've been using automatically-derived
serializers using the [`@Serializable`][Serializable] annotation as explained in 
the [Serializable classes](/docs/basic-serialization.md#serializable-classes) section or builtin serializers that were shown in 
the [Builtin classes](/docs/builtin-classes.md) section.

As a motivating example, let us take the following `Color` class with an integer value storing its `rgb` bytes.

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.json.*
-->

```kotlin
@Serializable
class Color(val rgb: Int)

fun main() {
    val green = Color(0x00ff00)
    println(Json.encodeToString(green))
}  
```              

> You can get the full code [here](../guide/example/example-serializer-01.kt).

By default, this class serializes its `rgb` property into JSON.

```text
{"rgb":65280}
```     

<!--- TEST -->

### Plugin-generated serializer

Every class marked with the `@Serializable` annotation, like the `Color` class from the previous example,
gets an instance of the [KSerializer] interface automatically generated by the Kotlin serialization compiler plugin.
We can retrieve this instance using `.serializer()` function on the class's companion object.

We can examine its [descriptor][KSerializer.descriptor] property that describes the structure of 
the serialized class. We'll learn more details about it in the upcoming sections.

<!--- INCLUDE 
import kotlinx.serialization.*

@Serializable
@SerialName("Color")
class Color(val rgb: Int)
-->

```kotlin
fun main() {
    val colorSerializer: KSerializer<Color> = Color.serializer()
    println(colorSerializer.descriptor)
} 
```             

> You can get the full code [here](../guide/example/example-serializer-02.kt).

```text
Color(rgb: kotlin.Int)
```

<!--- TEST -->

This serializer is automatically retrieved and used by the Kotlin serialization framework when the `Color` class
serialized on the top-level or used as a property of other classes.

> You cannot define your own function `serializer()` on a companion object of a serializable class. 

### Plugin-generated generic serializer

For generic classes, like the `Box` class shown in the [Generic classes](basic-serialization.md#generic-classes) section,
the automatically generated `.serializer()` function accepts as many parameters as there are type-parameters in the 
corresponding class. These parameters are of type [KSerializer], so the actual type argument's serializer has 
to be provided when constructing an instance of a serializer for a generic class.

<!--- INCLUDE 
import kotlinx.serialization.*

@Serializable
@SerialName("Color")
class Color(val rgb: Int)
-->

```kotlin
@Serializable           
@SerialName("Box")
class Box<T>(val contents: T)    

fun main() {
    val boxedColorSerializer = Box.serializer(Color.serializer())
    println(boxedColorSerializer.descriptor)
} 
```      

> You can get the full code [here](../guide/example/example-serializer-03.kt).                                                     

As we can see, a serializer was instantiated to serialize a concrete `Box<Color>`.

```text 
Box(contents: Color)
```       

<!--- TEST -->

### Builtin primitive serializers

The serializers for the [primitive builtin classes](builtin-classes.md#primitives) can be retrieved
using `.serializer()` extensions. 

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
-->

```kotlin 
fun main() {
    val intSerializer: KSerializer<Int> = Int.serializer()
    println(intSerializer.descriptor)
}
```

> You can get the full code [here](../guide/example/example-serializer-04.kt).   

<!--- TEST 
PrimitiveDescriptor(kotlin.Int)
--> 

### Constructing collection serializers

[Builtin collection serializers](builtin-classes.md#lists), when needed, must be explicitly constructed
using the corresponding functions [ListSerializer()], [SetSerializer()], [MapSerializer()], etc.
These classes are generic, so to instantiate their serializer we must provide the serializers for the
corresponding number of their type parameters.
For example, we can produce a serializer for a `List<String>` in the following way.

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
-->

```kotlin 
fun main() {   
    val stringListSerializer: KSerializer<List<String>> = ListSerializer(String.serializer()) 
    println(stringListSerializer.descriptor)
}
```

> You can get the full code [here](../guide/example/example-serializer-05.kt).  

<!--- TEST 
kotlin.collections.ArrayList(PrimitiveDescriptor(kotlin.String))
--> 

### Using top-level serializer function

When in doubt, you can always use the top-level generic [`serializer<T>()`][kotlinx.serialization.serializer] 
function to retrieve a serializer for an arbitrary Kotlin type in your source-code.

<!--- INCLUDE
import kotlinx.serialization.*
--><commit_msg>Fix failing `knitCheck` task on Windows<commit_after><!--- TEST_NAME SerializersTest -->

# Serializers

This is the third chapter of the [Kotlin Serialization Guide](serialization-guide.md).
In this chapter we'll take a look at serializers in more detail and see how custom serializers can be written.

**Table of contents**

<!--- TOC -->

* [Introduction to serializers](#introduction-to-serializers)
  * [Plugin-generated serializer](#plugin-generated-serializer)
  * [Plugin-generated generic serializer](#plugin-generated-generic-serializer)
  * [Builtin primitive serializers](#builtin-primitive-serializers)
  * [Constructing collection serializers](#constructing-collection-serializers)
  * [Using top-level serializer function](#using-top-level-serializer-function)
* [Custom serializers](#custom-serializers)
  * [Primitive serializer](#primitive-serializer)
  * [Composite serializer via surrogate](#composite-serializer-via-surrogate)
  * [Hand-written composite serializer](#hand-written-composite-serializer)
  * [Sequential decoding protocol (experimental)](#sequential-decoding-protocol-experimental)
  * [Serializing 3rd party classes](#serializing-3rd-party-classes)
  * [Passing a serializer manually](#passing-a-serializer-manually)
  * [Specifying serializer on a property](#specifying-serializer-on-a-property)
  * [Specifying serializers for a file](#specifying-serializers-for-a-file)
  * [Custom serializers for a generic type](#custom-serializers-for-a-generic-type)
  * [Format-specific serializers](#format-specific-serializers)
* [Contextual serialization](#contextual-serialization)
  * [Serializers module](#serializers-module)
* [Deriving external serializer for another Kotlin class (experimental)](#deriving-external-serializer-for-another-kotlin-class-experimental)
  * [External serialization uses properties](#external-serialization-uses-properties)

<!--- END -->

## Introduction to serializers

Format, like JSON, controls the _encoding_ of an object into specific output bytes, but how the object is decomposed 
into its constituent properties is controlled by a _serializer_. So far, we've been using automatically-derived
serializers using the [`@Serializable`][Serializable] annotation as explained in 
the [Serializable classes](/docs/basic-serialization.md#serializable-classes) section or builtin serializers that were shown in 
the [Builtin classes](/docs/builtin-classes.md) section.

As a motivating example, let us take the following `Color` class with an integer value storing its `rgb` bytes.

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.json.*
-->

```kotlin
@Serializable
class Color(val rgb: Int)

fun main() {
    val green = Color(0x00ff00)
    println(Json.encodeToString(green))
}  
```              

> You can get the full code [here](../guide/example/example-serializer-01.kt).

By default, this class serializes its `rgb` property into JSON.

```text
{"rgb":65280}
```     

<!--- TEST -->

### Plugin-generated serializer

Every class marked with the `@Serializable` annotation, like the `Color` class from the previous example,
gets an instance of the [KSerializer] interface automatically generated by the Kotlin serialization compiler plugin.
We can retrieve this instance using `.serializer()` function on the class's companion object.

We can examine its [descriptor][KSerializer.descriptor] property that describes the structure of 
the serialized class. We'll learn more details about it in the upcoming sections.

<!--- INCLUDE 
import kotlinx.serialization.*

@Serializable
@SerialName("Color")
class Color(val rgb: Int)
-->

```kotlin
fun main() {
    val colorSerializer: KSerializer<Color> = Color.serializer()
    println(colorSerializer.descriptor)
} 
```             

> You can get the full code [here](../guide/example/example-serializer-02.kt).

```text
Color(rgb: kotlin.Int)
```

<!--- TEST -->

This serializer is automatically retrieved and used by the Kotlin serialization framework when the `Color` class
serialized on the top-level or used as a property of other classes.

> You cannot define your own function `serializer()` on a companion object of a serializable class. 

### Plugin-generated generic serializer

For generic classes, like the `Box` class shown in the [Generic classes](basic-serialization.md#generic-classes) section,
the automatically generated `.serializer()` function accepts as many parameters as there are type-parameters in the 
corresponding class. These parameters are of type [KSerializer], so the actual type argument's serializer has 
to be provided when constructing an instance of a serializer for a generic class.

<!--- INCLUDE 
import kotlinx.serialization.*

@Serializable
@SerialName("Color")
class Color(val rgb: Int)
-->

```kotlin
@Serializable           
@SerialName("Box")
class Box<T>(val contents: T)    

fun main() {
    val boxedColorSerializer = Box.serializer(Color.serializer())
    println(boxedColorSerializer.descriptor)
} 
```      

> You can get the full code [here](../guide/example/example-serializer-03.kt).                                                     

As we can see, a serializer was instantiated to serialize a concrete `Box<Color>`.

```text 
Box(contents: Color)
```       

<!--- TEST -->

### Builtin primitive serializers

The serializers for the [primitive builtin classes](builtin-classes.md#primitives) can be retrieved
using `.serializer()` extensions. 

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
-->

```kotlin 
fun main() {
    val intSerializer: KSerializer<Int> = Int.serializer()
    println(intSerializer.descriptor)
}
```

> You can get the full code [here](../guide/example/example-serializer-04.kt).   

<!--- TEST 
PrimitiveDescriptor(kotlin.Int)
--> 

### Constructing collection serializers

[Builtin collection serializers](builtin-classes.md#lists), when needed, must be explicitly constructed
using the corresponding functions [ListSerializer()], [SetSerializer()], [MapSerializer()], etc.
These classes are generic, so to instantiate their serializer we must provide the serializers for the
corresponding number of their type parameters.
For example, we can produce a serializer for a `List<String>` in the following way.

<!--- INCLUDE
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
-->

```kotlin 
fun main() {   
    val stringListSerializer: KSerializer<List<String>> = ListSerializer(String.serializer()) 
    println(stringListSerializer.descriptor)
}
```

> You can get the full code [here](../guide/example/example-serializer-05.kt).  

<!--- TEST 
kotlin.collections.ArrayList(PrimitiveDescriptor(kotlin.String))
--> 

### Using top-level serializer function

When in doubt, you can always use the top-level generic `serializer<T>()`
function to retrieve a serializer for an arbitrary Kotlin type in your source-code.

<!--- INCLUDE
import kotlinx.serialization.*
-->
{'fraction_non_alphanumeric': 0.11284186346995909, 'fraction_numerical': 0.0031584236594645035, 'mean_word_length': 4.597428686219366, 'pattern_counts': {'":': 2, '<': 47, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2598186', 'n_tokens_mistral': 4027, 'n_tokens_neox': 3767, 'n_words': 1253}