• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!--- TEST_NAME SerializersTest -->
2
3# Serializers
4
5This is the third chapter of the [Kotlin Serialization Guide](serialization-guide.md).
6In this chapter we'll take a look at serializers in more detail, and we'll see how custom serializers can be written.
7
8**Table of contents**
9
10<!--- TOC -->
11
12* [Introduction to serializers](#introduction-to-serializers)
13  * [Plugin-generated serializer](#plugin-generated-serializer)
14  * [Plugin-generated generic serializer](#plugin-generated-generic-serializer)
15  * [Builtin primitive serializers](#builtin-primitive-serializers)
16  * [Constructing collection serializers](#constructing-collection-serializers)
17  * [Using top-level serializer function](#using-top-level-serializer-function)
18* [Custom serializers](#custom-serializers)
19  * [Primitive serializer](#primitive-serializer)
20  * [Delegating serializers](#delegating-serializers)
21  * [Composite serializer via surrogate](#composite-serializer-via-surrogate)
22  * [Handwritten composite serializer](#handwritten-composite-serializer)
23  * [Sequential decoding protocol (experimental)](#sequential-decoding-protocol-experimental)
24  * [Serializing 3rd party classes](#serializing-3rd-party-classes)
25  * [Passing a serializer manually](#passing-a-serializer-manually)
26  * [Specifying a serializer on a property](#specifying-a-serializer-on-a-property)
27  * [Specifying a serializer for a particular type](#specifying-a-serializer-for-a-particular-type)
28  * [Specifying serializers for a file](#specifying-serializers-for-a-file)
29  * [Specifying a serializer globally using a typealias](#specifying-a-serializer-globally-using-a-typealias)
30  * [Custom serializers for a generic type](#custom-serializers-for-a-generic-type)
31  * [Format-specific serializers](#format-specific-serializers)
32* [Simultaneous use of plugin-generated and custom serializers](#simultaneous-use-of-plugin-generated-and-custom-serializers)
33* [Contextual serialization](#contextual-serialization)
34  * [Serializers module](#serializers-module)
35  * [Contextual serialization and generic classes](#contextual-serialization-and-generic-classes)
36* [Deriving external serializer for another Kotlin class (experimental)](#deriving-external-serializer-for-another-kotlin-class-experimental)
37  * [External serialization uses properties](#external-serialization-uses-properties)
38
39<!--- END -->
40
41## Introduction to serializers
42
43Formats, like JSON, control the _encoding_ of an object into specific output bytes, but how the object is decomposed
44into its constituent properties is controlled by a _serializer_. So far we've been using automatically-derived
45serializers by using the [`@Serializable`][Serializable] annotation as explained in
46the [Serializable classes](/docs/basic-serialization.md#serializable-classes) section, or using builtin serializers that were shown in
47the [Builtin classes](/docs/builtin-classes.md) section.
48
49As a motivating example, let us take the following `Color` class with an integer value storing its `rgb` bytes.
50
51<!--- INCLUDE
52import kotlinx.serialization.*
53import kotlinx.serialization.json.*
54-->
55
56```kotlin
57@Serializable
58class Color(val rgb: Int)
59
60fun main() {
61    val green = Color(0x00ff00)
62    println(Json.encodeToString(green))
63}
64```
65
66> You can get the full code [here](../guide/example/example-serializer-01.kt).
67
68By default this class serializes its `rgb` property into JSON.
69
70```text
71{"rgb":65280}
72```
73
74<!--- TEST -->
75
76### Plugin-generated serializer
77
78Every class marked with the `@Serializable` annotation, like the `Color` class from the previous example,
79gets an instance of the [KSerializer] interface automatically generated by the Kotlin Serialization compiler plugin.
80We can retrieve this instance using the `.serializer()` function on the class's companion object.
81
82We can examine its [descriptor][KSerializer.descriptor] property that describes the structure of
83the serialized class. We'll learn more details about that in the upcoming sections.
84
85<!--- INCLUDE
86import kotlinx.serialization.*
87
88@Serializable
89@SerialName("Color")
90class Color(val rgb: Int)
91-->
92
93```kotlin
94fun main() {
95    val colorSerializer: KSerializer<Color> = Color.serializer()
96    println(colorSerializer.descriptor)
97}
98```
99
100> You can get the full code [here](../guide/example/example-serializer-02.kt).
101
102```text
103Color(rgb: kotlin.Int)
104```
105
106<!--- TEST -->
107
108This serializer is automatically retrieved and used by the Kotlin Serialization framework when the `Color` class
109is itself serialized, or when it is used as a property of other classes.
110
111> You cannot define your own function `serializer()` on a companion object of a serializable class.
112
113### Plugin-generated generic serializer
114
115For generic classes, like the `Box` class shown in the [Generic classes](basic-serialization.md#generic-classes) section,
116the automatically generated `.serializer()` function accepts as many parameters as there are type parameters in the
117corresponding class. These parameters are of type [KSerializer], so the actual type argument's serializer has
118to be provided when constructing an instance of a serializer for a generic class.
119
120<!--- INCLUDE
121import kotlinx.serialization.*
122
123@Serializable
124@SerialName("Color")
125class Color(val rgb: Int)
126-->
127
128```kotlin
129@Serializable
130@SerialName("Box")
131class Box<T>(val contents: T)
132
133fun main() {
134    val boxedColorSerializer = Box.serializer(Color.serializer())
135    println(boxedColorSerializer.descriptor)
136}
137```
138
139> You can get the full code [here](../guide/example/example-serializer-03.kt).
140
141As we can see, a serializer was instantiated to serialize a concrete `Box<Color>`.
142
143```text
144Box(contents: Color)
145```
146
147<!--- TEST -->
148
149### Builtin primitive serializers
150
151The serializers for the [primitive builtin classes](builtin-classes.md#primitives) can be retrieved
152using `.serializer()` extensions.
153
154<!--- INCLUDE
155import kotlinx.serialization.*
156import kotlinx.serialization.builtins.*
157-->
158
159```kotlin
160fun main() {
161    val intSerializer: KSerializer<Int> = Int.serializer()
162    println(intSerializer.descriptor)
163}
164```
165
166> You can get the full code [here](../guide/example/example-serializer-04.kt).
167
168```text
169PrimitiveDescriptor(kotlin.Int)
170```
171
172<!--- TEST -->
173
174### Constructing collection serializers
175
176[Builtin collection serializers](builtin-classes.md#lists), when needed, must be explicitly constructed
177using the corresponding functions [ListSerializer()], [SetSerializer()], [MapSerializer()], etc.
178These classes are generic, so to instantiate their serializer we must provide the serializers for the
179corresponding number of their type parameters.
180For example, we can produce a serializer for a `List<String>` in the following way.
181
182<!--- INCLUDE
183import kotlinx.serialization.*
184import kotlinx.serialization.builtins.*
185-->
186
187```kotlin
188fun main() {
189    val stringListSerializer: KSerializer<List<String>> = ListSerializer(String.serializer())
190    println(stringListSerializer.descriptor)
191}
192```
193
194> You can get the full code [here](../guide/example/example-serializer-05.kt).
195
196```text
197kotlin.collections.ArrayList(PrimitiveDescriptor(kotlin.String))
198```
199
200<!--- TEST -->
201
202### Using top-level serializer function
203
204When in doubt, you can always use the top-level generic `serializer<T>()`
205function to retrieve a serializer for an arbitrary Kotlin type in your source-code.
206
207<!--- INCLUDE
208import kotlinx.serialization.*
209-->
210
211```kotlin
212@Serializable
213@SerialName("Color")
214class Color(val rgb: Int)
215
216fun main() {
217    val stringToColorMapSerializer: KSerializer<Map<String, Color>> = serializer()
218    println(stringToColorMapSerializer.descriptor)
219}
220```
221
222> You can get the full code [here](../guide/example/example-serializer-06.kt).
223
224```text
225kotlin.collections.LinkedHashMap(PrimitiveDescriptor(kotlin.String), Color(rgb: kotlin.Int))
226```
227
228<!--- TEST -->
229
230## Custom serializers
231
232A plugin-generated serializer is convenient, but it may not produce the JSON we want
233for such a class as `Color`.
234Let's study the alternatives.
235
236### Primitive serializer
237
238We want to serialize the `Color` class as a hex string with the green color represented as `"00ff00"`.
239To achieve this, we write an object that implements the [KSerializer] interface for the `Color` class.
240
241<!--- INCLUDE .*-serializer-.*
242import kotlinx.serialization.*
243import kotlinx.serialization.json.*
244import kotlinx.serialization.encoding.*
245import kotlinx.serialization.descriptors.*
246-->
247
248```kotlin
249object ColorAsStringSerializer : KSerializer<Color> {
250    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Color", PrimitiveKind.STRING)
251
252    override fun serialize(encoder: Encoder, value: Color) {
253        val string = value.rgb.toString(16).padStart(6, '0')
254        encoder.encodeString(string)
255    }
256
257    override fun deserialize(decoder: Decoder): Color {
258        val string = decoder.decodeString()
259        return Color(string.toInt(16))
260    }
261}
262```
263
264A serializer has three required pieces.
265
266* The [serialize][SerializationStrategy.serialize] function implements [SerializationStrategy].
267  It receives an instance of [Encoder] and a value to serialize.
268  It uses the `encodeXxx` functions of `Encoder` to represent a value as a sequence of primitives. There is an
269  `encodeXxx` for each primitive type supported by serialization.
270  In our example, [encodeString][Encoder.encodeString] is used.
271
272* The [deserialize][DeserializationStrategy.deserialize] function implements [DeserializationStrategy].
273  It receives an instance of [Decoder] and returns a
274  deserialized value. It uses the `decodeXxx` functions of `Decoder`, which mirror the corresponding functions of `Encoder`.
275  In our example [decodeString][Decoder.decodeString] is used.
276
277* The [descriptor][KSerializer.descriptor] property must faithfully explain what exactly the `encodeXxx` and `decodeXxx`
278  functions do so that a format implementation knows in advance what encoding/decoding methods they call.
279  Some formats might also use it to generate a schema for the serialized data. For primitive serialization,
280  the [PrimitiveSerialDescriptor][PrimitiveSerialDescriptor()] function must be used with a unique name of the
281  type that is being serialized.
282  [PrimitiveKind] describes the specific `encodeXxx`/`decodeXxx` method that is being used in the implementation.
283
284> When the `descriptor` does not correspond to the encoding/decoding methods, then the behavior of the resulting code
285> is unspecified, and may arbitrarily change in future updates.
286
287The next step is to bind a serializer to a class. This is done with the [`@Serializable`][Serializable] annotation by adding
288the [`with`][Serializable.with] property value.
289
290```kotlin
291@Serializable(with = ColorAsStringSerializer::class)
292class Color(val rgb: Int)
293```
294
295Now we can serialize the `Color` class as we did before.
296
297```kotlin
298fun main() {
299    val green = Color(0x00ff00)
300    println(Json.encodeToString(green))
301}
302```
303
304> You can get the full code [here](../guide/example/example-serializer-07.kt).
305
306We get the serial representation as the hex string we wanted.
307
308```text
309"00ff00"
310```
311
312<!--- TEST -->
313
314Deserialization is also straightforward because we implemented the `deserialize` method.
315
316<!--- INCLUDE
317object ColorAsStringSerializer : KSerializer<Color> {
318    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Color", PrimitiveKind.STRING)
319
320    override fun serialize(encoder: Encoder, value: Color) {
321        val string = value.rgb.toString(16).padStart(6, '0')
322        encoder.encodeString(string)
323    }
324
325    override fun deserialize(decoder: Decoder): Color {
326        val string = decoder.decodeString()
327        return Color(string.toInt(16))
328    }
329}
330-->
331
332```kotlin
333@Serializable(with = ColorAsStringSerializer::class)
334class Color(val rgb: Int)
335
336fun main() {
337    val color = Json.decodeFromString<Color>("\"00ff00\"")
338    println(color.rgb) // prints 65280
339}
340```
341
342> You can get the full code [here](../guide/example/example-serializer-08.kt).
343
344<!--- TEST
34565280
346-->
347
348It also works if we serialize or deserialize a different class with `Color` properties.
349
350<!--- INCLUDE
351object ColorAsStringSerializer : KSerializer<Color> {
352    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Color", PrimitiveKind.STRING)
353
354    override fun serialize(encoder: Encoder, value: Color) {
355        val string = value.rgb.toString(16).padStart(6, '0')
356        encoder.encodeString(string)
357    }
358
359    override fun deserialize(decoder: Decoder): Color {
360        val string = decoder.decodeString()
361        return Color(string.toInt(16))
362    }
363}
364-->
365
366```kotlin
367@Serializable(with = ColorAsStringSerializer::class)
368data class Color(val rgb: Int)
369
370@Serializable
371data class Settings(val background: Color, val foreground: Color)
372
373fun main() {
374    val data = Settings(Color(0xffffff), Color(0))
375    val string = Json.encodeToString(data)
376    println(string)
377    require(Json.decodeFromString<Settings>(string) == data)
378}
379```
380
381> You can get the full code [here](../guide/example/example-serializer-09.kt).
382
383Both `Color` properties are serialized as strings.
384
385```text
386{"background":"ffffff","foreground":"000000"}
387```
388
389<!--- TEST -->
390
391### Delegating serializers
392
393In the previous example, we represented the `Color` class as a string.
394String is considered to be a primitive type, therefore we used `PrimitiveClassDescriptor` and specialized `encodeString` method.
395Now let's see what our actions would be if we have to serialize `Color` as another non-primitive type, let's say `IntArray`.
396
397An implementation of [KSerializer] for our original `Color` class is going to perform a conversion between
398`Color` and `IntArray`, but delegate the actual serialization logic to `IntArraySerializer`
399using [encodeSerializableValue][Encoder.encodeSerializableValue] and
400[decodeSerializableValue][Decoder.decodeSerializableValue].
401
402```kotlin
403import kotlinx.serialization.builtins.IntArraySerializer
404
405class ColorIntArraySerializer : KSerializer<Color> {
406    private val delegateSerializer = IntArraySerializer()
407    @OptIn(ExperimentalSerializationApi::class)
408    override val descriptor = SerialDescriptor("Color", delegateSerializer.descriptor)
409
410    override fun serialize(encoder: Encoder, value: Color) {
411        val data = intArrayOf(
412            (value.rgb shr 16) and 0xFF,
413            (value.rgb shr 8) and 0xFF,
414            value.rgb and 0xFF
415        )
416        encoder.encodeSerializableValue(delegateSerializer, data)
417    }
418
419    override fun deserialize(decoder: Decoder): Color {
420        val array = decoder.decodeSerializableValue(delegateSerializer)
421        return Color((array[0] shl 16) or (array[1] shl 8) or array[2])
422    }
423}
424```
425
426Note that we can't use default `Color.serializer().descriptor` here because formats that rely
427on the schema may think that we would call `encodeInt` instead of `encodeSerializableValue`.
428Neither we can use `IntArraySerializer().descriptor` directly — otherwise, formats that handle int arrays specially
429can't tell if `value` is really an `IntArray` or a `Color`.
430Don't worry, this optimization would still kick in when serializing the actual underlying int array.
431
432> An example of how a format can treat arrays specially is shown in the [formats guide](formats.md#format-specific-types).
433
434Now we can use the serializer:
435
436```kotlin
437@Serializable(with = ColorIntArraySerializer::class)
438class Color(val rgb: Int)
439
440fun main() {
441    val green = Color(0x00ff00)
442    println(Json.encodeToString(green))
443}
444```
445
446As you can see, such array representation is not very useful in JSON,
447but may save some space when used with a `ByteArray` and a binary format.
448
449> You can get the full code [here](../guide/example/example-serializer-10.kt).
450
451```text
452[0,255,0]
453```
454
455<!--- TEST -->
456
457
458### Composite serializer via surrogate
459
460Now our challenge is to get `Color` serialized so that it is represented in JSON as if it is a class
461with three properties&mdash;`r`, `g`, and `b`&mdash;so that JSON encodes it as an object.
462The easiest way to achieve this is to define a _surrogate_ class mimicking the serialized form of `Color` that
463we are going to use for its serialization. We also set the [SerialName] of this surrogate class to `Color`. Then if
464any format uses this name the surrogate looks like it is a `Color` class.
465The surrogate class can be `private`, and can enforce all the constraints on the serial representation
466of the class in its `init` block.
467
468```kotlin
469@Serializable
470@SerialName("Color")
471private class ColorSurrogate(val r: Int, val g: Int, val b: Int) {
472    init {
473        require(r in 0..255 && g in 0..255 && b in 0..255)
474    }
475}
476```
477
478> An example of where the class name is used is shown in
479> the [Custom subclass serial name](polymorphism.md#custom-subclass-serial-name) section in the chapter on polymorphism.
480
481Now we can use the `ColorSurrogate.serializer()` function to retrieve a plugin-generated serializer for the
482surrogate class.
483
484We can use the same approach as in [delegating serializer](#delegating-serializers), but this time,
485we are fully reusing an automatically
486generated [SerialDescriptor] for the surrogate because it should be indistinguishable from the original.
487
488```kotlin
489object ColorSerializer : KSerializer<Color> {
490    override val descriptor: SerialDescriptor = ColorSurrogate.serializer().descriptor
491
492    override fun serialize(encoder: Encoder, value: Color) {
493        val surrogate = ColorSurrogate((value.rgb shr 16) and 0xff, (value.rgb shr 8) and 0xff, value.rgb and 0xff)
494        encoder.encodeSerializableValue(ColorSurrogate.serializer(), surrogate)
495    }
496
497    override fun deserialize(decoder: Decoder): Color {
498        val surrogate = decoder.decodeSerializableValue(ColorSurrogate.serializer())
499        return Color((surrogate.r shl 16) or (surrogate.g shl 8) or surrogate.b)
500    }
501}
502```
503
504We bind the `ColorSerializer` serializer to the `Color` class.
505
506```kotlin
507@Serializable(with = ColorSerializer::class)
508class Color(val rgb: Int)
509```
510
511Now we can enjoy the result of serialization for the `Color` class.
512
513<!--- INCLUDE
514fun main() {
515    val green = Color(0x00ff00)
516    println(Json.encodeToString(green))
517}
518-->
519
520> You can get the full code [here](../guide/example/example-serializer-11.kt).
521
522```text
523{"r":0,"g":255,"b":0}
524```
525
526<!--- TEST -->
527
528### Handwritten composite serializer
529
530There are some cases where a surrogate solution does not fit. Perhaps we want to avoid the performance
531implications of additional allocation, or we want a configurable/dynamic set of properties for the
532resulting serial representation. In these cases we need to manually write a class
533serializer which mimics the behaviour of a generated serializer.
534
535```kotlin
536object ColorAsObjectSerializer : KSerializer<Color> {
537```
538
539Let's introduce it piece by piece. First, a descriptor is defined using the [buildClassSerialDescriptor] builder.
540The [element][ClassSerialDescriptorBuilder.element] function in the builder DSL automatically fetches serializers
541for the corresponding fields by their type. The order of elements is important. They are indexed starting from zero.
542
543```kotlin
544    override val descriptor: SerialDescriptor =
545        buildClassSerialDescriptor("Color") {
546            element<Int>("r")
547            element<Int>("g")
548            element<Int>("b")
549        }
550```
551
552> The "element" is a generic term here. What is an element of a descriptor depends on its [SerialKind].
553> Elements of a class descriptor are its properties, elements of a enum descriptor are its cases, etc.
554
555Then we write the `serialize` function using the [encodeStructure] DSL that provides access to
556the [CompositeEncoder] in its block. The difference between [Encoder] and [CompositeEncoder] is the latter
557has `encodeXxxElement` functions that correspond to the `encodeXxx` functions of the former. They must be called
558in the same order as in the descriptor.
559
560```kotlin
561    override fun serialize(encoder: Encoder, value: Color) =
562        encoder.encodeStructure(descriptor) {
563            encodeIntElement(descriptor, 0, (value.rgb shr 16) and 0xff)
564            encodeIntElement(descriptor, 1, (value.rgb shr 8) and 0xff)
565            encodeIntElement(descriptor, 2, value.rgb and 0xff)
566        }
567```
568
569The most complex piece of code is the `deserialize` function. It must support formats, like JSON, that
570can decode properties in an arbitrary order. It starts with the call to [decodeStructure] to
571get access to a [CompositeDecoder]. Inside it we write a loop that repeatedly calls
572[decodeElementIndex][CompositeDecoder.decodeElementIndex] to decode the index of the next element, then we decode the corresponding
573element using [decodeIntElement][CompositeDecoder.decodeIntElement] in our example, and finally we terminate the loop when
574`CompositeDecoder.DECODE_DONE` is encountered.
575
576```kotlin
577    override fun deserialize(decoder: Decoder): Color =
578        decoder.decodeStructure(descriptor) {
579            var r = -1
580            var g = -1
581            var b = -1
582            while (true) {
583                when (val index = decodeElementIndex(descriptor)) {
584                    0 -> r = decodeIntElement(descriptor, 0)
585                    1 -> g = decodeIntElement(descriptor, 1)
586                    2 -> b = decodeIntElement(descriptor, 2)
587                    CompositeDecoder.DECODE_DONE -> break
588                    else -> error("Unexpected index: $index")
589                }
590            }
591            require(r in 0..255 && g in 0..255 && b in 0..255)
592            Color((r shl 16) or (g shl 8) or b)
593        }
594```
595
596<!--- INCLUDE
597}
598-->
599
600Now we bind the resulting serializer to the `Color` class and test its serialization/deserialization.
601
602```kotlin
603@Serializable(with = ColorAsObjectSerializer::class)
604data class Color(val rgb: Int)
605
606fun main() {
607    val color = Color(0x00ff00)
608    val string = Json.encodeToString(color)
609    println(string)
610    require(Json.decodeFromString<Color>(string) == color)
611}
612```
613
614> You can get the full code [here](../guide/example/example-serializer-12.kt).
615
616As before, we got the `Color` class represented as a JSON object with three keys:
617
618```text
619{"r":0,"g":255,"b":0}
620```
621
622<!--- TEST -->
623
624### Sequential decoding protocol (experimental)
625
626The implementation of the `deserialize` function from the previous section works with any format. However,
627some formats either always store all the complex data in order or only do so sometimes (JSON always stores
628collections in order). With these formats the complex protocol of calling `decodeElementIndex` in a loop is
629unnecessary, and a faster implementation can be used if the [CompositeDecoder.decodeSequentially] function returns `true`.
630The plugin-generated serializers are actually conceptually similar to the code below.
631
632<!--- INCLUDE
633object ColorAsObjectSerializer : KSerializer<Color> {
634
635    override val descriptor: SerialDescriptor =
636        buildClassSerialDescriptor("Color") {
637            element<Int>("r")
638            element<Int>("g")
639            element<Int>("b")
640        }
641
642    override fun serialize(encoder: Encoder, value: Color) =
643        encoder.encodeStructure(descriptor) {
644            encodeIntElement(descriptor, 0, (value.rgb shr 16) and 0xff)
645            encodeIntElement(descriptor, 1, (value.rgb shr 8) and 0xff)
646            encodeIntElement(descriptor, 2, value.rgb and 0xff)
647        }
648-->
649
650```kotlin
651    override fun deserialize(decoder: Decoder): Color =
652        decoder.decodeStructure(descriptor) {
653            var r = -1
654            var g = -1
655            var b = -1
656            @OptIn(ExperimentalSerializationApi::class)
657            if (decodeSequentially()) { // sequential decoding protocol
658                r = decodeIntElement(descriptor, 0)
659                g = decodeIntElement(descriptor, 1)
660                b = decodeIntElement(descriptor, 2)
661            } else while (true) {
662                when (val index = decodeElementIndex(descriptor)) {
663                    0 -> r = decodeIntElement(descriptor, 0)
664                    1 -> g = decodeIntElement(descriptor, 1)
665                    2 -> b = decodeIntElement(descriptor, 2)
666                    CompositeDecoder.DECODE_DONE -> break
667                    else -> error("Unexpected index: $index")
668                }
669            }
670            require(r in 0..255 && g in 0..255 && b in 0..255)
671            Color((r shl 16) or (g shl 8) or b)
672        }
673```
674
675<!--- INCLUDE
676}
677
678@Serializable(with = ColorAsObjectSerializer::class)
679data class Color(val rgb: Int)
680
681fun main() {
682    val color = Color(0x00ff00)
683    val string = Json.encodeToString(color)
684    println(string)
685    require(Json.decodeFromString<Color>(string) == color)
686}
687-->
688
689> You can get the full code [here](../guide/example/example-serializer-13.kt).
690
691<!--- TEST
692{"r":0,"g":255,"b":0}
693-->
694
695### Serializing 3rd party classes
696
697Sometimes an application has to work with an external type that is not serializable.
698Let us use [java.util.Date] as an example. As before, we start by writing an implementation of [KSerializer]
699for the class. Our goal is to get a `Date` serialized as a long number of milliseconds following the
700approach from the [Primitive serializer](#primitive-serializer) section.
701
702> In the following sections any kind of `Date` serializer would work. For example, if we want `Date` to be serialized
703> as an object, we would use an approach from
704> the [Composite serializer via surrogate](#composite-serializer-via-surrogate) section.
705> See also [Deriving external serializer for another Kotlin class (experimental)](#deriving-external-serializer-for-another-kotlin-class-experimental)
706> when you need to serialize a 3rd-party Kotlin class that could have been serializable, but is not.
707
708<!--- INCLUDE
709import java.util.Date
710import java.text.SimpleDateFormat
711-->
712
713```kotlin
714object DateAsLongSerializer : KSerializer<Date> {
715    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
716    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
717    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
718}
719```
720
721We cannot bind the `DateAsLongSerializer` serializer to the `Date` class with the [`@Serializable`][Serializable] annotation
722because we don't control the `Date` source code. There are several ways to work around that.
723
724### Passing a serializer manually
725
726The `encodeToXxx` and `decodeFromXxx` functions offer overloaded versions
727that accept either a [SerializationStrategy] or [DeserializationStrategy] as their first parameter, respectively.
728This feature allows you
729to provide a custom serializer for types that aren't annotated with [`@Serializable`][Serializable] by default.
730
731This approach is particularly useful
732when working with non-serializable classes like `Date` as the top-level object being serialized.
733Here's an example:
734
735```kotlin
736fun main() {
737    val kotlin10ReleaseDate = SimpleDateFormat("yyyy-MM-ddX").parse("2016-02-15+00")
738    println(Json.encodeToString(DateAsLongSerializer, kotlin10ReleaseDate))
739}
740```
741
742> You can get the full code [here](../guide/example/example-serializer-14.kt).
743
744```text
7451455494400000
746```
747
748<!--- TEST -->
749
750### Specifying a serializer on a property
751
752When a property of a non-serializable class, like `Date`, is serialized as part of a serializable class we must supply
753its serializer or the code will not compile. This is accomplished using the [`@Serializable`][Serializable] annotation on the property.
754
755<!--- INCLUDE
756import java.util.Date
757import java.text.SimpleDateFormat
758
759object DateAsLongSerializer : KSerializer<Date> {
760    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
761    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
762    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
763}
764-->
765
766```kotlin
767@Serializable
768class ProgrammingLanguage(
769    val name: String,
770    @Serializable(with = DateAsLongSerializer::class)
771    val stableReleaseDate: Date
772)
773
774fun main() {
775    val data = ProgrammingLanguage("Kotlin", SimpleDateFormat("yyyy-MM-ddX").parse("2016-02-15+00"))
776    println(Json.encodeToString(data))
777}
778```
779
780> You can get the full code [here](../guide/example/example-serializer-15.kt).
781
782The `stableReleaseDate` property is serialized with the serialization strategy that we specified for it:
783
784```text
785{"name":"Kotlin","stableReleaseDate":1455494400000}
786```
787
788<!--- TEST -->
789
790### Specifying a serializer for a particular type
791
792[`@Serializable`][Serializable] annotation can also be applied directly to the types.
793This is handy when a class that requires a custom serializer, such as `Date`, happens to be a generic type argument.
794The most common use case for that is when you have a list of dates:
795
796<!--- INCLUDE
797import java.util.Date
798import java.text.SimpleDateFormat
799
800object DateAsLongSerializer : KSerializer<Date> {
801    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
802    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
803    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
804}
805-->
806
807```kotlin
808@Serializable
809class ProgrammingLanguage(
810    val name: String,
811    val releaseDates: List<@Serializable(DateAsLongSerializer::class) Date>
812)
813
814fun main() {
815    val df = SimpleDateFormat("yyyy-MM-ddX")
816    val data = ProgrammingLanguage("Kotlin", listOf(df.parse("2023-07-06+00"), df.parse("2023-04-25+00"), df.parse("2022-12-28+00")))
817    println(Json.encodeToString(data))
818}
819```
820
821> You can get the full code [here](../guide/example/example-serializer-16.kt).
822
823```text
824{"name":"Kotlin","releaseDates":[1688601600000,1682380800000,1672185600000]}
825```
826
827<!--- TEST -->
828
829### Specifying serializers for a file
830
831A serializer for a specific type, like `Date`, can be specified for a whole source code file with the file-level
832[UseSerializers] annotation at the beginning of the file.
833
834```kotlin
835@file:UseSerializers(DateAsLongSerializer::class)
836```
837
838<!--- PREFIX -->
839
840<!--- INCLUDE
841import java.util.Date
842import java.text.SimpleDateFormat
843
844object DateAsLongSerializer : KSerializer<Date> {
845    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
846    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
847    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
848}
849-->
850
851Now a `Date` property can be used in a serializable class without additional annotations.
852
853```kotlin
854@Serializable
855class ProgrammingLanguage(val name: String, val stableReleaseDate: Date)
856
857fun main() {
858    val data = ProgrammingLanguage("Kotlin", SimpleDateFormat("yyyy-MM-ddX").parse("2016-02-15+00"))
859    println(Json.encodeToString(data))
860}
861```
862> You can get the full code [here](../guide/example/example-serializer-17.kt).
863
864```text
865{"name":"Kotlin","stableReleaseDate":1455494400000}
866```
867
868<!--- TEST -->
869
870### Specifying a serializer globally using a typealias
871
872kotlinx.serialization tends to be the always-explicit framework when it comes to serialization strategies: normally,
873they should be explicitly mentioned in `@Serializable` annotation. Therefore, we do not provide any kind of global serializer
874configuration (except for [context serializer](#contextual-serialization) mentioned later).
875
876However, in projects with a large number of files and classes, it may be too cumbersome to specify `@file:UseSerializers`
877every time, especially for classes like `Date` or `Instant` that have a fixed strategy of serialization across the project.
878For such cases, it is possible to specify serializers using `typealias`es, as they preserve annotations, including serialization-related ones:
879<!--- INCLUDE
880import java.util.Date
881import java.util.TimeZone
882import java.text.SimpleDateFormat
883
884object DateAsLongSerializer : KSerializer<Date> {
885    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DateAsLong", PrimitiveKind.LONG)
886    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
887    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
888}
889
890object DateAsSimpleTextSerializer: KSerializer<Date> {
891    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DateAsSimpleText", PrimitiveKind.LONG)
892    private val format = SimpleDateFormat("yyyy-MM-dd").apply {
893        // Here we explicitly set time zone to UTC so output for this sample remains locale-independent.
894        // Depending on your needs, you may have to adjust or remove this line.
895        setTimeZone(TimeZone.getTimeZone("UTC"))
896    }
897    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeString(format.format(value))
898    override fun deserialize(decoder: Decoder): Date = format.parse(decoder.decodeString())
899}
900-->
901
902```kotlin
903typealias DateAsLong = @Serializable(DateAsLongSerializer::class) Date
904
905typealias DateAsText = @Serializable(DateAsSimpleTextSerializer::class) Date
906```
907
908Using these new different types, it is possible to serialize a Date differently without additional annotations:
909
910```kotlin
911@Serializable
912class ProgrammingLanguage(val stableReleaseDate: DateAsText, val lastReleaseTimestamp: DateAsLong)
913
914fun main() {
915    val format = SimpleDateFormat("yyyy-MM-ddX")
916    val data = ProgrammingLanguage(format.parse("2016-02-15+00"), format.parse("2022-07-07+00"))
917    println(Json.encodeToString(data))
918}
919```
920
921> You can get the full code [here](../guide/example/example-serializer-18.kt).
922
923```text
924{"stableReleaseDate":"2016-02-15","lastReleaseTimestamp":1657152000000}
925```
926
927<!--- TEST -->
928
929### Custom serializers for a generic type
930
931Let us take a look at the following example of the generic `Box<T>` class.
932It is marked with `@Serializable(with = BoxSerializer::class)` as we plan to have a custom serialization
933strategy for it.
934
935```kotlin
936@Serializable(with = BoxSerializer::class)
937data class Box<T>(val contents: T)
938```
939
940An implementation of [KSerializer] for a regular type is written as an `object`, as we saw in this chapter's
941examples for the `Color` type. A generic class serializer is instantiated with serializers
942for its generic parameters. We saw this in the [Plugin-generated generic serializer](#plugin-generated-generic-serializer) section.
943A custom serializer for a generic class must be a `class` with a constructor that accepts as many [KSerializer]
944parameters as the type has generic parameters. Let us write a `Box<T>` serializer that erases itself during
945serialization, delegating everything to the underlying serializer of its `data` property.
946
947```kotlin
948class BoxSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<Box<T>> {
949    override val descriptor: SerialDescriptor = dataSerializer.descriptor
950    override fun serialize(encoder: Encoder, value: Box<T>) = dataSerializer.serialize(encoder, value.contents)
951    override fun deserialize(decoder: Decoder) = Box(dataSerializer.deserialize(decoder))
952}
953```
954
955Now we can serialize and deserialize `Box<Project>`.
956
957```kotlin
958@Serializable
959data class Project(val name: String)
960
961fun main() {
962    val box = Box(Project("kotlinx.serialization"))
963    val string = Json.encodeToString(box)
964    println(string)
965    println(Json.decodeFromString<Box<Project>>(string))
966}
967```
968
969> You can get the full code [here](../guide/example/example-serializer-19.kt).
970
971The resulting JSON looks like the `Project` class was serialized directly.
972
973```text
974{"name":"kotlinx.serialization"}
975Box(contents=Project(name=kotlinx.serialization))
976```
977
978<!--- TEST -->
979
980### Format-specific serializers
981
982The above custom serializers worked in the same way for every format. However, there might be format-specific
983features that a serializer implementation would like to take advantage of.
984
985* The [Json transformations](json.md#json-transformations) section of the [Json](json.md) chapter provides examples
986  of serializers that utilize JSON-specific features.
987
988* A format implementation can have a format-specific representation for a type as explained
989  in the [Format-specific types](formats.md#format-specific-types) section of
990  the [Alternative and custom formats (experimental)](formats.md) chapter.
991
992This chapter proceeds with a generic approach to tweaking the serialization strategy based on the context.
993
994## Simultaneous use of plugin-generated and custom serializers
995In some cases it may be useful to have a serialization plugin continue to generate a serializer even if a custom one is used for the class.
996
997The most common examples are: using a plugin-generated serializer for fallback strategy, accessing type structure via [descriptor][KSerializer.descriptor] of plugin-generated serializer, use default serialization behavior in descendants that do not use custom serializers.
998
999In order for the plugin to continue generating the serializer, you must specify the `@KeepGeneratedSerializer` annotation in the type declaration.
1000In this case, the serializer will be accessible using the `.generatedSerializer()` function on the class's companion object.
1001
1002> This annotation is currently experimental. Kotlin 2.0.20 or higher is required for this feature to work.
1003
1004Annotation `@KeepGeneratedSerializer` is not allowed on classes involved in polymorphic serialization: interfaces, sealed classes, abstract classes, classes marked by [Polymorphic].
1005
1006An example of using two serializers at once:
1007
1008<!--- INCLUDE
1009object ColorAsStringSerializer : KSerializer<Color> {
1010    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Color", PrimitiveKind.STRING)
1011
1012    override fun serialize(encoder: Encoder, value: Color) {
1013        val string = value.rgb.toString(16).padStart(6, '0')
1014        encoder.encodeString(string)
1015    }
1016
1017    override fun deserialize(decoder: Decoder): Color {
1018        val string = decoder.decodeString()
1019        return Color(string.toInt(16))
1020    }
1021}
1022-->
1023
1024```kotlin
1025@OptIn(ExperimentalSerializationApi::class)
1026@KeepGeneratedSerializer
1027@Serializable(with = ColorAsStringSerializer::class)
1028class Color(val rgb: Int)
1029
1030
1031fun main() {
1032    val green = Color(0x00ff00)
1033    println(Json.encodeToString(green))
1034    println(Json.encodeToString(Color.generatedSerializer(), green))
1035}
1036```
1037
1038> You can get the full code [here](../guide/example/example-serializer-20.kt).
1039
1040As a result, serialization will occur using custom and plugin-generated serializers:
1041
1042```text
1043"00ff00"
1044{"rgb":65280}
1045```
1046
1047<!--- TEST -->
1048
1049## Contextual serialization
1050
1051All the previous approaches to specifying custom serialization strategies were _static_, that is
1052fully defined at compile-time. The exception was the [Passing a serializer manually](#passing-a-serializer-manually)
1053approach, but it worked only on a top-level object. You might need to change the serialization
1054strategy for objects deep in the serialized object tree at run-time, with the strategy being selected in a context-dependent way.
1055For example, you might want to represent `java.util.Date` in JSON format as an ISO 8601 string or as a long integer
1056depending on a version of a protocol you are serializing data for. This is called _contextual_ serialization, and it
1057is supported by a built-in [ContextualSerializer] class. Usually we don't have to use this serializer class explicitly&mdash;there
1058is the [Contextual] annotation providing a shortcut to
1059the `@Serializable(with = ContextualSerializer::class)` annotation,
1060or the [UseContextualSerialization] annotation can be used at the file-level just like
1061the [UseSerializers] annotation. Let's see an example utilizing the former.
1062
1063<!--- INCLUDE
1064import java.util.Date
1065import java.text.SimpleDateFormat
1066-->
1067
1068```kotlin
1069@Serializable
1070class ProgrammingLanguage(
1071    val name: String,
1072    @Contextual
1073    val stableReleaseDate: Date
1074)
1075```
1076
1077<!--- INCLUDE
1078
1079fun main() {
1080    val data = ProgrammingLanguage("Kotlin", SimpleDateFormat("yyyy-MM-ddX").parse("2016-02-15+00"))
1081    println(Json.encodeToString(data))
1082}
1083-->
1084
1085To actually serialize this class we must provide the corresponding context when calling the `encodeToXxx`/`decodeFromXxx`
1086functions. Without it we'll get a "Serializer for class 'Date' is not found" exception.
1087
1088> See [here](../guide/example/example-serializer-21.kt) for an example that produces that exception.
1089
1090<!--- TEST LINES_START
1091Exception in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'Date' is not found.
1092Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
1093-->
1094
1095<!--- INCLUDE
1096import kotlinx.serialization.modules.*
1097import java.util.Date
1098import java.text.SimpleDateFormat
1099
1100object DateAsLongSerializer : KSerializer<Date> {
1101    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
1102    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
1103    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
1104}
1105
1106@Serializable
1107class ProgrammingLanguage(
1108    val name: String,
1109    @Contextual
1110    val stableReleaseDate: Date
1111)
1112-->
1113
1114### Serializers module
1115
1116To provide a context, we define a [SerializersModule] instance that describes which serializers shall be used
1117at run-time to serialize which contextually-serializable classes. This is done using the
1118[SerializersModule {}][SerializersModule()] builder function, which provides the [SerializersModuleBuilder] DSL to
1119register serializers. In the example below we use the [contextual][_contextual] function with the serializer. The corresponding
1120class this serializer is defined for is fetched automatically via the `reified` type parameter.
1121
1122```kotlin
1123private val module = SerializersModule {
1124    contextual(DateAsLongSerializer)
1125}
1126```
1127
1128Next we create an instance of the [Json] format with this module using the
1129[Json {}][Json()] builder function and the [serializersModule][JsonBuilder.serializersModule] property.
1130
1131> Details on custom JSON configurations can be found in
1132> the [JSON configuration](json.md#json-configuration) section.
1133
1134```kotlin
1135val format = Json { serializersModule = module }
1136```
1137
1138Now we can serialize our data with this `format`.
1139
1140```kotlin
1141fun main() {
1142    val data = ProgrammingLanguage("Kotlin", SimpleDateFormat("yyyy-MM-ddX").parse("2016-02-15+00"))
1143    println(format.encodeToString(data))
1144}
1145```
1146
1147> You can get the full code [here](../guide/example/example-serializer-22.kt).
1148```text
1149{"name":"Kotlin","stableReleaseDate":1455494400000}
1150```
1151
1152<!--- TEST -->
1153
1154### Contextual serialization and generic classes
1155
1156In the previous section we saw that we can register serializer instance in the module for a class we want to serialize contextually.
1157We also know that [serializers for generic classes have constructor parameters](#custom-serializers-for-a-generic-type) — type arguments serializers.
1158It means that we can't use one serializer instance for a class if this class is generic:
1159
1160```kotlin
1161val incorrectModule = SerializersModule {
1162    // Can serialize only Box<Int>, but not Box<String> or others
1163    contextual(BoxSerializer(Int.serializer()))
1164}
1165```
1166
1167For cases when one want to serialize contextually a generic class, it is possible to register provider in the module:
1168
1169```kotlin
1170val correctModule = SerializersModule {
1171    // args[0] contains Int.serializer() or String.serializer(), depending on the usage
1172    contextual(Box::class) { args -> BoxSerializer(args[0]) }
1173}
1174```
1175
1176<!--- CLEAR -->
1177
1178> Additional details on serialization modules are given in
1179> the [Merging library serializers modules](polymorphism.md#merging-library-serializers-modules) section of
1180> the [Polymorphism](polymorphism.md) chapter.
1181
1182## Deriving external serializer for another Kotlin class (experimental)
1183
1184If a 3rd-party class to be serialized is a Kotlin class with a properties-only primary constructor, a kind of
1185class which could have been made `@Serializable`, then you can generate an _external_ serializer for it
1186using the [Serializer] annotation on an object with the [`forClass`][Serializer.forClass] property.
1187
1188```kotlin
1189// NOT @Serializable
1190class Project(val name: String, val language: String)
1191
1192@OptIn(ExperimentalSerializationApi::class)
1193@Serializer(forClass = Project::class)
1194object ProjectSerializer
1195```
1196
1197You must bind this serializer to a class using one of the approaches explained in this chapter. We'll
1198follow the [Passing a serializer manually](#passing-a-serializer-manually) approach for this example.
1199
1200```kotlin
1201fun main() {
1202    val data = Project("kotlinx.serialization", "Kotlin")
1203    println(Json.encodeToString(ProjectSerializer, data))
1204}
1205```
1206
1207> You can get the full code [here](../guide/example/example-serializer-23.kt).
1208
1209This gets all the `Project` properties serialized:
1210
1211```text
1212{"name":"kotlinx.serialization","language":"Kotlin"}
1213```
1214
1215<!--- TEST -->
1216
1217### External serialization uses properties
1218
1219As we saw earlier, the regular `@Serializable` annotation creates a serializer so that
1220[Backing fields are serialized](basic-serialization.md#backing-fields-are-serialized). _External_ serialization using
1221`Serializer(forClass = ...)` has no access to backing fields and works differently.
1222It serializes only _accessible_ properties that have setters or are part of the primary constructor.
1223The following example shows this.
1224
1225```kotlin
1226// NOT @Serializable, will use external serializer
1227class Project(
1228    // val in a primary constructor -- serialized
1229    val name: String
1230) {
1231    var stars: Int = 0 // property with getter & setter -- serialized
1232
1233    val path: String // getter only -- not serialized
1234        get() = "kotlin/$name"
1235
1236    private var locked: Boolean = false // private, not accessible -- not serialized
1237}
1238
1239@OptIn(ExperimentalSerializationApi::class)
1240@Serializer(forClass = Project::class)
1241object ProjectSerializer
1242
1243fun main() {
1244    val data = Project("kotlinx.serialization").apply { stars = 9000 }
1245    println(Json.encodeToString(ProjectSerializer, data))
1246}
1247```
1248
1249> You can get the full code [here](../guide/example/example-serializer-24.kt).
1250
1251The output is shown below.
1252
1253```text
1254{"name":"kotlinx.serialization","stars":9000}
1255```
1256
1257<!--- TEST -->
1258
1259---
1260
1261The next chapter covers [Polymorphism](polymorphism.md).
1262
1263<!-- Java references -->
1264[java.util.Date]: https://docs.oracle.com/javase/8/docs/api/java/util/Date.html
1265
1266<!--- MODULE /kotlinx-serialization-core -->
1267<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
1268
1269[Serializable]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
1270[KSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-k-serializer/index.html
1271[KSerializer.descriptor]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-k-serializer/descriptor.html
1272[SerializationStrategy.serialize]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serialization-strategy/serialize.html
1273[SerializationStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serialization-strategy/index.html
1274[DeserializationStrategy.deserialize]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-deserialization-strategy/deserialize.html
1275[DeserializationStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-deserialization-strategy/index.html
1276[Serializable.with]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/with.html
1277[SerialName]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
1278[UseSerializers]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-use-serializers/index.html
1279[Polymorphic]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-polymorphic/index.html
1280[ContextualSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-contextual-serializer/index.html
1281[Contextual]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-contextual/index.html
1282[UseContextualSerialization]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-use-contextual-serialization/index.html
1283[Serializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializer/index.html
1284[Serializer.forClass]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializer/for-class.html
1285
1286<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.builtins -->
1287
1288[ListSerializer()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.builtins/-list-serializer.html
1289[SetSerializer()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.builtins/-set-serializer.html
1290[MapSerializer()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.builtins/-map-serializer.html
1291
1292<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.encoding -->
1293
1294[Encoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-encoder/index.html
1295[Encoder.encodeString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-encoder/encode-string.html
1296[Decoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-decoder/index.html
1297[Decoder.decodeString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-decoder/decode-string.html
1298[Encoder.encodeSerializableValue]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-encoder/encode-serializable-value.html
1299[Decoder.decodeSerializableValue]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-decoder/decode-serializable-value.html
1300[encodeStructure]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/encode-structure.html
1301[CompositeEncoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-composite-encoder/index.html
1302[decodeStructure]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/decode-structure.html
1303[CompositeDecoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-composite-decoder/index.html
1304[CompositeDecoder.decodeElementIndex]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-composite-decoder/decode-element-index.html
1305[CompositeDecoder.decodeIntElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-composite-decoder/decode-int-element.html
1306[CompositeDecoder.decodeSequentially]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-composite-decoder/decode-sequentially.html
1307
1308<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.descriptors -->
1309
1310[PrimitiveSerialDescriptor()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-primitive-serial-descriptor.html
1311[PrimitiveKind]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-primitive-kind/index.html
1312[SerialDescriptor]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-serial-descriptor/index.html
1313[buildClassSerialDescriptor]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/build-class-serial-descriptor.html
1314[ClassSerialDescriptorBuilder.element]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/element.html
1315[SerialKind]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-serial-kind/index.html
1316
1317<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.modules -->
1318
1319[SerializersModule]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module/index.html
1320[SerializersModule()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module.html
1321[SerializersModuleBuilder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module-builder/index.html
1322[_contextual]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/contextual.html
1323
1324<!--- MODULE /kotlinx-serialization-json -->
1325<!--- INDEX kotlinx-serialization-json/kotlinx.serialization.json -->
1326
1327[Json]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html
1328[Json()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json.html
1329[JsonBuilder.serializersModule]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/serializers-module.html
1330
1331<!--- END -->
1332
1333