xref: /aosp_15_r20/external/kotlinx.serialization/docs/basic-serialization.md (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST_NAME BasicSerializationTest -->
2*57b5a4a6SAndroid Build Coastguard Worker
3*57b5a4a6SAndroid Build Coastguard Worker# Basic Serialization
4*57b5a4a6SAndroid Build Coastguard Worker
5*57b5a4a6SAndroid Build Coastguard WorkerThis is the first chapter of the [Kotlin Serialization Guide](serialization-guide.md).
6*57b5a4a6SAndroid Build Coastguard WorkerThis chapter shows the basic use of Kotlin Serialization and explains its core concepts.
7*57b5a4a6SAndroid Build Coastguard Worker
8*57b5a4a6SAndroid Build Coastguard Worker**Table of contents**
9*57b5a4a6SAndroid Build Coastguard Worker
10*57b5a4a6SAndroid Build Coastguard Worker<!--- TOC -->
11*57b5a4a6SAndroid Build Coastguard Worker
12*57b5a4a6SAndroid Build Coastguard Worker* [Basics](#basics)
13*57b5a4a6SAndroid Build Coastguard Worker  * [JSON encoding](#json-encoding)
14*57b5a4a6SAndroid Build Coastguard Worker  * [JSON decoding](#json-decoding)
15*57b5a4a6SAndroid Build Coastguard Worker* [Serializable classes](#serializable-classes)
16*57b5a4a6SAndroid Build Coastguard Worker  * [Backing fields are serialized](#backing-fields-are-serialized)
17*57b5a4a6SAndroid Build Coastguard Worker  * [Constructor properties requirement](#constructor-properties-requirement)
18*57b5a4a6SAndroid Build Coastguard Worker  * [Data validation](#data-validation)
19*57b5a4a6SAndroid Build Coastguard Worker  * [Optional properties](#optional-properties)
20*57b5a4a6SAndroid Build Coastguard Worker  * [Optional property initializer call](#optional-property-initializer-call)
21*57b5a4a6SAndroid Build Coastguard Worker  * [Required properties](#required-properties)
22*57b5a4a6SAndroid Build Coastguard Worker  * [Transient properties](#transient-properties)
23*57b5a4a6SAndroid Build Coastguard Worker  * [Defaults are not encoded by default](#defaults-are-not-encoded-by-default)
24*57b5a4a6SAndroid Build Coastguard Worker  * [Nullable properties](#nullable-properties)
25*57b5a4a6SAndroid Build Coastguard Worker  * [Type safety is enforced](#type-safety-is-enforced)
26*57b5a4a6SAndroid Build Coastguard Worker  * [Referenced objects](#referenced-objects)
27*57b5a4a6SAndroid Build Coastguard Worker  * [No compression of repeated references](#no-compression-of-repeated-references)
28*57b5a4a6SAndroid Build Coastguard Worker  * [Generic classes](#generic-classes)
29*57b5a4a6SAndroid Build Coastguard Worker  * [Serial field names](#serial-field-names)
30*57b5a4a6SAndroid Build Coastguard Worker
31*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
32*57b5a4a6SAndroid Build Coastguard Worker
33*57b5a4a6SAndroid Build Coastguard Worker## Basics
34*57b5a4a6SAndroid Build Coastguard Worker
35*57b5a4a6SAndroid Build Coastguard WorkerTo convert an object tree to a string or to a sequence of bytes, it must come
36*57b5a4a6SAndroid Build Coastguard Workerthrough two mutually intertwined processes. In the first step, an object is _serialized_&mdash;it
37*57b5a4a6SAndroid Build Coastguard Workeris converted into a serial sequence of its constituting primitive values. This process is common for all
38*57b5a4a6SAndroid Build Coastguard Workerdata formats and its result depends on the object being serialized. A _serializer_ controls this process.
39*57b5a4a6SAndroid Build Coastguard WorkerThe second step is called _encoding_&mdash;it is the conversion of the corresponding sequence of primitives into
40*57b5a4a6SAndroid Build Coastguard Workerthe output format representation. An _encoder_ controls this process. Whenever the distinction is not important,
41*57b5a4a6SAndroid Build Coastguard Workerboth the terms of encoding and serialization are used interchangeably.
42*57b5a4a6SAndroid Build Coastguard Worker
43*57b5a4a6SAndroid Build Coastguard Worker```
44*57b5a4a6SAndroid Build Coastguard Worker+---------+  Serialization  +------------+  Encoding  +---------------+
45*57b5a4a6SAndroid Build Coastguard Worker| Objects | --------------> | Primitives | ---------> | Output format |
46*57b5a4a6SAndroid Build Coastguard Worker+---------+                 +------------+            +---------------+
47*57b5a4a6SAndroid Build Coastguard Worker```
48*57b5a4a6SAndroid Build Coastguard Worker
49*57b5a4a6SAndroid Build Coastguard WorkerThe reverse process starts with parsing of the input format and _decoding_ of primitive values,
50*57b5a4a6SAndroid Build Coastguard Workerfollowed by _deserialization_ of the resulting stream into objects. We'll see details of this process later.
51*57b5a4a6SAndroid Build Coastguard Worker
52*57b5a4a6SAndroid Build Coastguard WorkerFor now, we start with [JSON](https://json.org) encoding.
53*57b5a4a6SAndroid Build Coastguard Worker
54*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE .*-basic-.*
55*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.*
56*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.json.*
57*57b5a4a6SAndroid Build Coastguard Worker-->
58*57b5a4a6SAndroid Build Coastguard Worker
59*57b5a4a6SAndroid Build Coastguard Worker### JSON encoding
60*57b5a4a6SAndroid Build Coastguard Worker
61*57b5a4a6SAndroid Build Coastguard WorkerThe whole process of converting data into a specific format is called _encoding_. For JSON we encode data
62*57b5a4a6SAndroid Build Coastguard Workerusing the [Json.encodeToString][kotlinx.serialization.encodeToString] extension function. It serializes
63*57b5a4a6SAndroid Build Coastguard Workerthe object that is passed as its parameter under the hood and encodes it to a JSON string.
64*57b5a4a6SAndroid Build Coastguard Worker
65*57b5a4a6SAndroid Build Coastguard WorkerLet's start with a class describing a project and try to get its JSON representation.
66*57b5a4a6SAndroid Build Coastguard Worker
67*57b5a4a6SAndroid Build Coastguard Worker```kotlin
68*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val language: String)
69*57b5a4a6SAndroid Build Coastguard Worker
70*57b5a4a6SAndroid Build Coastguard Workerfun main() {
71*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin")
72*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
73*57b5a4a6SAndroid Build Coastguard Worker}
74*57b5a4a6SAndroid Build Coastguard Worker```
75*57b5a4a6SAndroid Build Coastguard Worker
76*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-basic-01.kt).
77*57b5a4a6SAndroid Build Coastguard Worker
78*57b5a4a6SAndroid Build Coastguard WorkerWhen we run this code we get the exception.
79*57b5a4a6SAndroid Build Coastguard Worker
80*57b5a4a6SAndroid Build Coastguard Worker```text
81*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'Project' is not found.
82*57b5a4a6SAndroid Build Coastguard WorkerPlease ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
83*57b5a4a6SAndroid Build Coastguard Worker```
84*57b5a4a6SAndroid Build Coastguard Worker
85*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
86*57b5a4a6SAndroid Build Coastguard Worker
87*57b5a4a6SAndroid Build Coastguard WorkerSerializable classes have to be explicitly marked. Kotlin Serialization does not use reflection,
88*57b5a4a6SAndroid Build Coastguard Workerso you cannot accidentally deserialize a class which was not supposed to be serializable. We fix it by
89*57b5a4a6SAndroid Build Coastguard Workeradding the [`@Serializable`][Serializable] annotation.
90*57b5a4a6SAndroid Build Coastguard Worker
91*57b5a4a6SAndroid Build Coastguard Worker```kotlin
92*57b5a4a6SAndroid Build Coastguard Worker@Serializable
93*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val language: String)
94*57b5a4a6SAndroid Build Coastguard Worker
95*57b5a4a6SAndroid Build Coastguard Workerfun main() {
96*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin")
97*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
98*57b5a4a6SAndroid Build Coastguard Worker}
99*57b5a4a6SAndroid Build Coastguard Worker```
100*57b5a4a6SAndroid Build Coastguard Worker
101*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-basic-02.kt).
102*57b5a4a6SAndroid Build Coastguard Worker
103*57b5a4a6SAndroid Build Coastguard WorkerThe `@Serializable` annotation instructs the Kotlin Serialization plugin to automatically generate and hook
104*57b5a4a6SAndroid Build Coastguard Workerup a _serializer_ for this class. Now the output of the example is the corresponding JSON.
105*57b5a4a6SAndroid Build Coastguard Worker
106*57b5a4a6SAndroid Build Coastguard Worker```text
107*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","language":"Kotlin"}
108*57b5a4a6SAndroid Build Coastguard Worker```
109*57b5a4a6SAndroid Build Coastguard Worker
110*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
111*57b5a4a6SAndroid Build Coastguard Worker
112*57b5a4a6SAndroid Build Coastguard Worker> There is a whole chapter about the [Serializers](serializers.md). For now, it is enough to know
113*57b5a4a6SAndroid Build Coastguard Worker> that they are automatically generated by the Kotlin Serialization plugin.
114*57b5a4a6SAndroid Build Coastguard Worker
115*57b5a4a6SAndroid Build Coastguard Worker### JSON decoding
116*57b5a4a6SAndroid Build Coastguard Worker
117*57b5a4a6SAndroid Build Coastguard WorkerThe reverse process is called _decoding_. To decode a JSON string into an object, we'll
118*57b5a4a6SAndroid Build Coastguard Workeruse the [Json.decodeFromString][kotlinx.serialization.decodeFromString] extension function.
119*57b5a4a6SAndroid Build Coastguard WorkerTo specify which type we want to get as a result, we provide a type parameter to this function.
120*57b5a4a6SAndroid Build Coastguard Worker
121*57b5a4a6SAndroid Build Coastguard WorkerAs we'll see later, serialization works with different kinds of classes.
122*57b5a4a6SAndroid Build Coastguard WorkerHere we are marking our `Project` class as a `data class`, not because it is required, but because
123*57b5a4a6SAndroid Build Coastguard Workerwe want to print its contents to verify how it decodes.
124*57b5a4a6SAndroid Build Coastguard Worker
125*57b5a4a6SAndroid Build Coastguard Worker```kotlin
126*57b5a4a6SAndroid Build Coastguard Worker@Serializable
127*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String)
128*57b5a4a6SAndroid Build Coastguard Worker
129*57b5a4a6SAndroid Build Coastguard Workerfun main() {
130*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
131*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":"Kotlin"}
132*57b5a4a6SAndroid Build Coastguard Worker    """)
133*57b5a4a6SAndroid Build Coastguard Worker    println(data)
134*57b5a4a6SAndroid Build Coastguard Worker}
135*57b5a4a6SAndroid Build Coastguard Worker```
136*57b5a4a6SAndroid Build Coastguard Worker
137*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-basic-03.kt).
138*57b5a4a6SAndroid Build Coastguard Worker
139*57b5a4a6SAndroid Build Coastguard WorkerRunning this code we get back the object.
140*57b5a4a6SAndroid Build Coastguard Worker
141*57b5a4a6SAndroid Build Coastguard Worker```text
142*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin)
143*57b5a4a6SAndroid Build Coastguard Worker```
144*57b5a4a6SAndroid Build Coastguard Worker
145*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
146*57b5a4a6SAndroid Build Coastguard Worker
147*57b5a4a6SAndroid Build Coastguard Worker## Serializable classes
148*57b5a4a6SAndroid Build Coastguard Worker
149*57b5a4a6SAndroid Build Coastguard WorkerThis section goes into more details on how different `@Serializable` classes are handled.
150*57b5a4a6SAndroid Build Coastguard Worker
151*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE .*-classes-.*
152*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.*
153*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.json.*
154*57b5a4a6SAndroid Build Coastguard Worker-->
155*57b5a4a6SAndroid Build Coastguard Worker
156*57b5a4a6SAndroid Build Coastguard Worker### Backing fields are serialized
157*57b5a4a6SAndroid Build Coastguard Worker
158*57b5a4a6SAndroid Build Coastguard WorkerOnly a class's properties with backing fields are serialized, so properties with a getter/setter that don't
159*57b5a4a6SAndroid Build Coastguard Workerhave a backing field and delegated properties are not serialized, as the following example shows.
160*57b5a4a6SAndroid Build Coastguard Worker
161*57b5a4a6SAndroid Build Coastguard Worker```kotlin
162*57b5a4a6SAndroid Build Coastguard Worker@Serializable
163*57b5a4a6SAndroid Build Coastguard Workerclass Project(
164*57b5a4a6SAndroid Build Coastguard Worker    // name is a property with backing field -- serialized
165*57b5a4a6SAndroid Build Coastguard Worker    var name: String
166*57b5a4a6SAndroid Build Coastguard Worker) {
167*57b5a4a6SAndroid Build Coastguard Worker    var stars: Int = 0 // property with a backing field -- serialized
168*57b5a4a6SAndroid Build Coastguard Worker
169*57b5a4a6SAndroid Build Coastguard Worker    val path: String // getter only, no backing field -- not serialized
170*57b5a4a6SAndroid Build Coastguard Worker        get() = "kotlin/$name"
171*57b5a4a6SAndroid Build Coastguard Worker
172*57b5a4a6SAndroid Build Coastguard Worker    var id by ::name // delegated property -- not serialized
173*57b5a4a6SAndroid Build Coastguard Worker}
174*57b5a4a6SAndroid Build Coastguard Worker
175*57b5a4a6SAndroid Build Coastguard Workerfun main() {
176*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization").apply { stars = 9000 }
177*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
178*57b5a4a6SAndroid Build Coastguard Worker}
179*57b5a4a6SAndroid Build Coastguard Worker```
180*57b5a4a6SAndroid Build Coastguard Worker
181*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-01.kt).
182*57b5a4a6SAndroid Build Coastguard Worker
183*57b5a4a6SAndroid Build Coastguard WorkerWe can clearly see that only the `name` and `stars` properties are present in the JSON output.
184*57b5a4a6SAndroid Build Coastguard Worker
185*57b5a4a6SAndroid Build Coastguard Worker```text
186*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","stars":9000}
187*57b5a4a6SAndroid Build Coastguard Worker```
188*57b5a4a6SAndroid Build Coastguard Worker
189*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
190*57b5a4a6SAndroid Build Coastguard Worker
191*57b5a4a6SAndroid Build Coastguard Worker### Constructor properties requirement
192*57b5a4a6SAndroid Build Coastguard Worker
193*57b5a4a6SAndroid Build Coastguard WorkerIf we want to define the `Project` class so that it takes a path string, and then
194*57b5a4a6SAndroid Build Coastguard Workerdeconstructs it into the corresponding properties, we might be tempted to write something like the code below.
195*57b5a4a6SAndroid Build Coastguard Worker
196*57b5a4a6SAndroid Build Coastguard Worker```kotlin
197*57b5a4a6SAndroid Build Coastguard Worker@Serializable
198*57b5a4a6SAndroid Build Coastguard Workerclass Project(path: String) {
199*57b5a4a6SAndroid Build Coastguard Worker    val owner: String = path.substringBefore('/')
200*57b5a4a6SAndroid Build Coastguard Worker    val name: String = path.substringAfter('/')
201*57b5a4a6SAndroid Build Coastguard Worker}
202*57b5a4a6SAndroid Build Coastguard Worker```
203*57b5a4a6SAndroid Build Coastguard Worker
204*57b5a4a6SAndroid Build Coastguard Worker<!--- CLEAR -->
205*57b5a4a6SAndroid Build Coastguard Worker
206*57b5a4a6SAndroid Build Coastguard WorkerThis class does not compile because the `@Serializable` annotation requires that all parameters of the class's primary
207*57b5a4a6SAndroid Build Coastguard Workerconstructor be properties. A simple workaround is to define a private primary constructor with the class's
208*57b5a4a6SAndroid Build Coastguard Workerproperties, and turn the constructor we wanted into the secondary one.
209*57b5a4a6SAndroid Build Coastguard Worker
210*57b5a4a6SAndroid Build Coastguard Worker```kotlin
211*57b5a4a6SAndroid Build Coastguard Worker@Serializable
212*57b5a4a6SAndroid Build Coastguard Workerclass Project private constructor(val owner: String, val name: String) {
213*57b5a4a6SAndroid Build Coastguard Worker    constructor(path: String) : this(
214*57b5a4a6SAndroid Build Coastguard Worker        owner = path.substringBefore('/'),
215*57b5a4a6SAndroid Build Coastguard Worker        name = path.substringAfter('/')
216*57b5a4a6SAndroid Build Coastguard Worker    )
217*57b5a4a6SAndroid Build Coastguard Worker
218*57b5a4a6SAndroid Build Coastguard Worker    val path: String
219*57b5a4a6SAndroid Build Coastguard Worker        get() = "$owner/$name"
220*57b5a4a6SAndroid Build Coastguard Worker}
221*57b5a4a6SAndroid Build Coastguard Worker```
222*57b5a4a6SAndroid Build Coastguard Worker
223*57b5a4a6SAndroid Build Coastguard WorkerSerialization works with a private primary constructor, and still serializes only backing fields.
224*57b5a4a6SAndroid Build Coastguard Worker
225*57b5a4a6SAndroid Build Coastguard Worker```kotlin
226*57b5a4a6SAndroid Build Coastguard Workerfun main() {
227*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(Project("kotlin/kotlinx.serialization")))
228*57b5a4a6SAndroid Build Coastguard Worker}
229*57b5a4a6SAndroid Build Coastguard Worker```
230*57b5a4a6SAndroid Build Coastguard Worker
231*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-02.kt).
232*57b5a4a6SAndroid Build Coastguard Worker
233*57b5a4a6SAndroid Build Coastguard WorkerThis example produces the expected output.
234*57b5a4a6SAndroid Build Coastguard Worker
235*57b5a4a6SAndroid Build Coastguard Worker```text
236*57b5a4a6SAndroid Build Coastguard Worker{"owner":"kotlin","name":"kotlinx.serialization"}
237*57b5a4a6SAndroid Build Coastguard Worker```
238*57b5a4a6SAndroid Build Coastguard Worker
239*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
240*57b5a4a6SAndroid Build Coastguard Worker
241*57b5a4a6SAndroid Build Coastguard Worker### Data validation
242*57b5a4a6SAndroid Build Coastguard Worker
243*57b5a4a6SAndroid Build Coastguard WorkerAnother case where you might want to introduce a primary constructor parameter without a property is when you
244*57b5a4a6SAndroid Build Coastguard Workerwant to validate its value before storing it to a property. To make it serializable you shall replace it
245*57b5a4a6SAndroid Build Coastguard Workerwith a property in the primary constructor, and move the validation to an `init { ... }` block.
246*57b5a4a6SAndroid Build Coastguard Worker
247*57b5a4a6SAndroid Build Coastguard Worker```kotlin
248*57b5a4a6SAndroid Build Coastguard Worker@Serializable
249*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String) {
250*57b5a4a6SAndroid Build Coastguard Worker    init {
251*57b5a4a6SAndroid Build Coastguard Worker        require(name.isNotEmpty()) { "name cannot be empty" }
252*57b5a4a6SAndroid Build Coastguard Worker    }
253*57b5a4a6SAndroid Build Coastguard Worker}
254*57b5a4a6SAndroid Build Coastguard Worker```
255*57b5a4a6SAndroid Build Coastguard Worker
256*57b5a4a6SAndroid Build Coastguard WorkerA deserialization process works like a regular constructor in Kotlin and calls all `init` blocks, ensuring that you
257*57b5a4a6SAndroid Build Coastguard Workercannot get an invalid class as a result of deserialization. Let's try it.
258*57b5a4a6SAndroid Build Coastguard Worker
259*57b5a4a6SAndroid Build Coastguard Worker```kotlin
260*57b5a4a6SAndroid Build Coastguard Workerfun main() {
261*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
262*57b5a4a6SAndroid Build Coastguard Worker        {"name":""}
263*57b5a4a6SAndroid Build Coastguard Worker    """)
264*57b5a4a6SAndroid Build Coastguard Worker    println(data)
265*57b5a4a6SAndroid Build Coastguard Worker}
266*57b5a4a6SAndroid Build Coastguard Worker```
267*57b5a4a6SAndroid Build Coastguard Worker
268*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-03.kt).
269*57b5a4a6SAndroid Build Coastguard Worker
270*57b5a4a6SAndroid Build Coastguard WorkerRunning this code produces the exception:
271*57b5a4a6SAndroid Build Coastguard Worker
272*57b5a4a6SAndroid Build Coastguard Worker```text
273*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" java.lang.IllegalArgumentException: name cannot be empty
274*57b5a4a6SAndroid Build Coastguard Worker```
275*57b5a4a6SAndroid Build Coastguard Worker
276*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
277*57b5a4a6SAndroid Build Coastguard Worker
278*57b5a4a6SAndroid Build Coastguard Worker### Optional properties
279*57b5a4a6SAndroid Build Coastguard Worker
280*57b5a4a6SAndroid Build Coastguard WorkerAn object can be deserialized only when all its properties are present in the input.
281*57b5a4a6SAndroid Build Coastguard WorkerFor example, run the following code.
282*57b5a4a6SAndroid Build Coastguard Worker
283*57b5a4a6SAndroid Build Coastguard Worker```kotlin
284*57b5a4a6SAndroid Build Coastguard Worker@Serializable
285*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String)
286*57b5a4a6SAndroid Build Coastguard Worker
287*57b5a4a6SAndroid Build Coastguard Workerfun main() {
288*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
289*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization"}
290*57b5a4a6SAndroid Build Coastguard Worker    """)
291*57b5a4a6SAndroid Build Coastguard Worker    println(data)
292*57b5a4a6SAndroid Build Coastguard Worker}
293*57b5a4a6SAndroid Build Coastguard Worker```
294*57b5a4a6SAndroid Build Coastguard Worker
295*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-04.kt).
296*57b5a4a6SAndroid Build Coastguard Worker
297*57b5a4a6SAndroid Build Coastguard WorkerIt produces the exception:
298*57b5a4a6SAndroid Build Coastguard Worker
299*57b5a4a6SAndroid Build Coastguard Worker```text
300*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.MissingFieldException: Field 'language' is required for type with serial name 'example.exampleClasses04.Project', but it was missing at path: $
301*57b5a4a6SAndroid Build Coastguard Worker```
302*57b5a4a6SAndroid Build Coastguard Worker
303*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
304*57b5a4a6SAndroid Build Coastguard Worker
305*57b5a4a6SAndroid Build Coastguard WorkerThis problem can be fixed by adding a default value to the property, which automatically makes it optional
306*57b5a4a6SAndroid Build Coastguard Workerfor serialization.
307*57b5a4a6SAndroid Build Coastguard Worker
308*57b5a4a6SAndroid Build Coastguard Worker```kotlin
309*57b5a4a6SAndroid Build Coastguard Worker@Serializable
310*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String = "Kotlin")
311*57b5a4a6SAndroid Build Coastguard Worker
312*57b5a4a6SAndroid Build Coastguard Workerfun main() {
313*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
314*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization"}
315*57b5a4a6SAndroid Build Coastguard Worker    """)
316*57b5a4a6SAndroid Build Coastguard Worker    println(data)
317*57b5a4a6SAndroid Build Coastguard Worker}
318*57b5a4a6SAndroid Build Coastguard Worker```
319*57b5a4a6SAndroid Build Coastguard Worker
320*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-05.kt).
321*57b5a4a6SAndroid Build Coastguard Worker
322*57b5a4a6SAndroid Build Coastguard WorkerIt produces the following output with the default value for the `language` property.
323*57b5a4a6SAndroid Build Coastguard Worker
324*57b5a4a6SAndroid Build Coastguard Worker```text
325*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin)
326*57b5a4a6SAndroid Build Coastguard Worker```
327*57b5a4a6SAndroid Build Coastguard Worker
328*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
329*57b5a4a6SAndroid Build Coastguard Worker
330*57b5a4a6SAndroid Build Coastguard Worker### Optional property initializer call
331*57b5a4a6SAndroid Build Coastguard Worker
332*57b5a4a6SAndroid Build Coastguard WorkerWhen an optional property is present in the input, the corresponding initializer for this
333*57b5a4a6SAndroid Build Coastguard Workerproperty is not even called. This is a feature designed for performance, so be careful not
334*57b5a4a6SAndroid Build Coastguard Workerto rely on side effects in initializers. Consider the example below.
335*57b5a4a6SAndroid Build Coastguard Worker
336*57b5a4a6SAndroid Build Coastguard Worker```kotlin
337*57b5a4a6SAndroid Build Coastguard Workerfun computeLanguage(): String {
338*57b5a4a6SAndroid Build Coastguard Worker    println("Computing")
339*57b5a4a6SAndroid Build Coastguard Worker    return "Kotlin"
340*57b5a4a6SAndroid Build Coastguard Worker}
341*57b5a4a6SAndroid Build Coastguard Worker
342*57b5a4a6SAndroid Build Coastguard Worker@Serializable
343*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String = computeLanguage())
344*57b5a4a6SAndroid Build Coastguard Worker
345*57b5a4a6SAndroid Build Coastguard Workerfun main() {
346*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
347*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":"Kotlin"}
348*57b5a4a6SAndroid Build Coastguard Worker    """)
349*57b5a4a6SAndroid Build Coastguard Worker    println(data)
350*57b5a4a6SAndroid Build Coastguard Worker}
351*57b5a4a6SAndroid Build Coastguard Worker```
352*57b5a4a6SAndroid Build Coastguard Worker
353*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-06.kt).
354*57b5a4a6SAndroid Build Coastguard Worker
355*57b5a4a6SAndroid Build Coastguard WorkerSince the `language` property was specified in the input, we don't see the "Computing" string printed
356*57b5a4a6SAndroid Build Coastguard Workerin the output.
357*57b5a4a6SAndroid Build Coastguard Worker
358*57b5a4a6SAndroid Build Coastguard Worker```text
359*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin)
360*57b5a4a6SAndroid Build Coastguard Worker```
361*57b5a4a6SAndroid Build Coastguard Worker
362*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
363*57b5a4a6SAndroid Build Coastguard Worker
364*57b5a4a6SAndroid Build Coastguard Worker### Required properties
365*57b5a4a6SAndroid Build Coastguard Worker
366*57b5a4a6SAndroid Build Coastguard WorkerA property with a default value can be required in a serial format with the [`@Required`][Required] annotation.
367*57b5a4a6SAndroid Build Coastguard WorkerLet us change the previous example by marking the `language` property as `@Required`.
368*57b5a4a6SAndroid Build Coastguard Worker
369*57b5a4a6SAndroid Build Coastguard Worker```kotlin
370*57b5a4a6SAndroid Build Coastguard Worker@Serializable
371*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, @Required val language: String = "Kotlin")
372*57b5a4a6SAndroid Build Coastguard Worker
373*57b5a4a6SAndroid Build Coastguard Workerfun main() {
374*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
375*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization"}
376*57b5a4a6SAndroid Build Coastguard Worker    """)
377*57b5a4a6SAndroid Build Coastguard Worker    println(data)
378*57b5a4a6SAndroid Build Coastguard Worker}
379*57b5a4a6SAndroid Build Coastguard Worker```
380*57b5a4a6SAndroid Build Coastguard Worker
381*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-07.kt).
382*57b5a4a6SAndroid Build Coastguard Worker
383*57b5a4a6SAndroid Build Coastguard WorkerWe get the following exception.
384*57b5a4a6SAndroid Build Coastguard Worker
385*57b5a4a6SAndroid Build Coastguard Worker```text
386*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.MissingFieldException: Field 'language' is required for type with serial name 'example.exampleClasses07.Project', but it was missing at path: $
387*57b5a4a6SAndroid Build Coastguard Worker```
388*57b5a4a6SAndroid Build Coastguard Worker
389*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
390*57b5a4a6SAndroid Build Coastguard Worker
391*57b5a4a6SAndroid Build Coastguard Worker### Transient properties
392*57b5a4a6SAndroid Build Coastguard Worker
393*57b5a4a6SAndroid Build Coastguard WorkerA property can be excluded from serialization by marking it with the [`@Transient`][Transient] annotation
394*57b5a4a6SAndroid Build Coastguard Worker(don't confuse it with [kotlin.jvm.Transient]). Transient properties must have a default value.
395*57b5a4a6SAndroid Build Coastguard Worker
396*57b5a4a6SAndroid Build Coastguard Worker```kotlin
397*57b5a4a6SAndroid Build Coastguard Worker@Serializable
398*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, @Transient val language: String = "Kotlin")
399*57b5a4a6SAndroid Build Coastguard Worker
400*57b5a4a6SAndroid Build Coastguard Workerfun main() {
401*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
402*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":"Kotlin"}
403*57b5a4a6SAndroid Build Coastguard Worker    """)
404*57b5a4a6SAndroid Build Coastguard Worker    println(data)
405*57b5a4a6SAndroid Build Coastguard Worker}
406*57b5a4a6SAndroid Build Coastguard Worker```
407*57b5a4a6SAndroid Build Coastguard Worker
408*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-08.kt).
409*57b5a4a6SAndroid Build Coastguard Worker
410*57b5a4a6SAndroid Build Coastguard WorkerAttempts to explicitly specify its value in the serial format, even if the specified
411*57b5a4a6SAndroid Build Coastguard Workervalue is equal to the default one, produces the following exception.
412*57b5a4a6SAndroid Build Coastguard Worker
413*57b5a4a6SAndroid Build Coastguard Worker```text
414*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 42: Encountered an unknown key 'language' at path: $.name
415*57b5a4a6SAndroid Build Coastguard WorkerUse 'ignoreUnknownKeys = true' in 'Json {}' builder to ignore unknown keys.
416*57b5a4a6SAndroid Build Coastguard Worker```
417*57b5a4a6SAndroid Build Coastguard Worker
418*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
419*57b5a4a6SAndroid Build Coastguard Worker
420*57b5a4a6SAndroid Build Coastguard Worker> The 'ignoreUnknownKeys' feature is explained in the [Ignoring Unknown Keys section](json.md#ignoring-unknown-keys) section.
421*57b5a4a6SAndroid Build Coastguard Worker
422*57b5a4a6SAndroid Build Coastguard Worker### Defaults are not encoded by default
423*57b5a4a6SAndroid Build Coastguard Worker
424*57b5a4a6SAndroid Build Coastguard WorkerDefault values are not encoded by default in JSON. This behavior is motivated by the fact that in most real-life scenarios
425*57b5a4a6SAndroid Build Coastguard Workersuch configuration reduces visual clutter, and saves the amount of data being serialized.
426*57b5a4a6SAndroid Build Coastguard Worker
427*57b5a4a6SAndroid Build Coastguard Worker```kotlin
428*57b5a4a6SAndroid Build Coastguard Worker@Serializable
429*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String = "Kotlin")
430*57b5a4a6SAndroid Build Coastguard Worker
431*57b5a4a6SAndroid Build Coastguard Workerfun main() {
432*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization")
433*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
434*57b5a4a6SAndroid Build Coastguard Worker}
435*57b5a4a6SAndroid Build Coastguard Worker```
436*57b5a4a6SAndroid Build Coastguard Worker
437*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-09.kt).
438*57b5a4a6SAndroid Build Coastguard Worker
439*57b5a4a6SAndroid Build Coastguard WorkerIt produces the following output, which does not have the `language` property because its value is equal to the default one.
440*57b5a4a6SAndroid Build Coastguard Worker
441*57b5a4a6SAndroid Build Coastguard Worker```text
442*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization"}
443*57b5a4a6SAndroid Build Coastguard Worker```
444*57b5a4a6SAndroid Build Coastguard Worker
445*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
446*57b5a4a6SAndroid Build Coastguard Worker
447*57b5a4a6SAndroid Build Coastguard WorkerSee JSON's [Encoding defaults](json.md#encoding-defaults) section on how this behavior can be configured for JSON.
448*57b5a4a6SAndroid Build Coastguard WorkerAdditionally, this behavior can be controlled without taking format settings into account.
449*57b5a4a6SAndroid Build Coastguard WorkerFor that purposes, [EncodeDefault] annotation can be used:
450*57b5a4a6SAndroid Build Coastguard Worker
451*57b5a4a6SAndroid Build Coastguard Worker```kotlin
452*57b5a4a6SAndroid Build Coastguard Worker@Serializable
453*57b5a4a6SAndroid Build Coastguard Workerdata class Project(
454*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
455*57b5a4a6SAndroid Build Coastguard Worker    @EncodeDefault val language: String = "Kotlin"
456*57b5a4a6SAndroid Build Coastguard Worker)
457*57b5a4a6SAndroid Build Coastguard Worker```
458*57b5a4a6SAndroid Build Coastguard Worker
459*57b5a4a6SAndroid Build Coastguard WorkerThis annotation instructs the framework to always serialize property, regardless of its value or format settings.
460*57b5a4a6SAndroid Build Coastguard WorkerIt's also possible to tweak it into the opposite behavior using [EncodeDefault.Mode] parameter:
461*57b5a4a6SAndroid Build Coastguard Worker
462*57b5a4a6SAndroid Build Coastguard Worker```kotlin
463*57b5a4a6SAndroid Build Coastguard Worker
464*57b5a4a6SAndroid Build Coastguard Worker@Serializable
465*57b5a4a6SAndroid Build Coastguard Workerdata class User(
466*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
467*57b5a4a6SAndroid Build Coastguard Worker    @EncodeDefault(EncodeDefault.Mode.NEVER) val projects: List<Project> = emptyList()
468*57b5a4a6SAndroid Build Coastguard Worker)
469*57b5a4a6SAndroid Build Coastguard Worker
470*57b5a4a6SAndroid Build Coastguard Workerfun main() {
471*57b5a4a6SAndroid Build Coastguard Worker    val userA = User("Alice", listOf(Project("kotlinx.serialization")))
472*57b5a4a6SAndroid Build Coastguard Worker    val userB = User("Bob")
473*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(userA))
474*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(userB))
475*57b5a4a6SAndroid Build Coastguard Worker}
476*57b5a4a6SAndroid Build Coastguard Worker```
477*57b5a4a6SAndroid Build Coastguard Worker
478*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-10.kt).
479*57b5a4a6SAndroid Build Coastguard Worker
480*57b5a4a6SAndroid Build Coastguard WorkerAs you can see, `language` property is preserved and `projects` is omitted:
481*57b5a4a6SAndroid Build Coastguard Worker
482*57b5a4a6SAndroid Build Coastguard Worker```text
483*57b5a4a6SAndroid Build Coastguard Worker{"name":"Alice","projects":[{"name":"kotlinx.serialization","language":"Kotlin"}]}
484*57b5a4a6SAndroid Build Coastguard Worker{"name":"Bob"}
485*57b5a4a6SAndroid Build Coastguard Worker```
486*57b5a4a6SAndroid Build Coastguard Worker
487*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
488*57b5a4a6SAndroid Build Coastguard Worker
489*57b5a4a6SAndroid Build Coastguard Worker### Nullable properties
490*57b5a4a6SAndroid Build Coastguard Worker
491*57b5a4a6SAndroid Build Coastguard WorkerNullable properties are natively supported by Kotlin Serialization.
492*57b5a4a6SAndroid Build Coastguard Worker
493*57b5a4a6SAndroid Build Coastguard Worker```kotlin
494*57b5a4a6SAndroid Build Coastguard Worker@Serializable
495*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val renamedTo: String? = null)
496*57b5a4a6SAndroid Build Coastguard Worker
497*57b5a4a6SAndroid Build Coastguard Workerfun main() {
498*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization")
499*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
500*57b5a4a6SAndroid Build Coastguard Worker}
501*57b5a4a6SAndroid Build Coastguard Worker```
502*57b5a4a6SAndroid Build Coastguard Worker
503*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-11.kt).
504*57b5a4a6SAndroid Build Coastguard Worker
505*57b5a4a6SAndroid Build Coastguard WorkerThis example does not encode `null` in JSON because [Defaults are not encoded](#defaults-are-not-encoded).
506*57b5a4a6SAndroid Build Coastguard Worker
507*57b5a4a6SAndroid Build Coastguard Worker```text
508*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization"}
509*57b5a4a6SAndroid Build Coastguard Worker```
510*57b5a4a6SAndroid Build Coastguard Worker
511*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
512*57b5a4a6SAndroid Build Coastguard Worker
513*57b5a4a6SAndroid Build Coastguard Worker### Type safety is enforced
514*57b5a4a6SAndroid Build Coastguard Worker
515*57b5a4a6SAndroid Build Coastguard WorkerKotlin Serialization strongly enforces the type safety of the Kotlin programming language.
516*57b5a4a6SAndroid Build Coastguard WorkerIn particular, let us try to decode a `null` value from a JSON object into a non-nullable Kotlin property `language`.
517*57b5a4a6SAndroid Build Coastguard Worker
518*57b5a4a6SAndroid Build Coastguard Worker```kotlin
519*57b5a4a6SAndroid Build Coastguard Worker@Serializable
520*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String = "Kotlin")
521*57b5a4a6SAndroid Build Coastguard Worker
522*57b5a4a6SAndroid Build Coastguard Workerfun main() {
523*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromString<Project>("""
524*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":null}
525*57b5a4a6SAndroid Build Coastguard Worker    """)
526*57b5a4a6SAndroid Build Coastguard Worker    println(data)
527*57b5a4a6SAndroid Build Coastguard Worker}
528*57b5a4a6SAndroid Build Coastguard Worker```
529*57b5a4a6SAndroid Build Coastguard Worker
530*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-12.kt).
531*57b5a4a6SAndroid Build Coastguard Worker
532*57b5a4a6SAndroid Build Coastguard WorkerEven though the `language` property has a default value, it is still an error to attempt to assign
533*57b5a4a6SAndroid Build Coastguard Workerthe `null` value to it.
534*57b5a4a6SAndroid Build Coastguard Worker
535*57b5a4a6SAndroid Build Coastguard Worker```text
536*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 52: Expected string literal but 'null' literal was found at path: $.language
537*57b5a4a6SAndroid Build Coastguard WorkerUse 'coerceInputValues = true' in 'Json {}' builder to coerce nulls if property has a default value.
538*57b5a4a6SAndroid Build Coastguard Worker```
539*57b5a4a6SAndroid Build Coastguard Worker
540*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
541*57b5a4a6SAndroid Build Coastguard Worker
542*57b5a4a6SAndroid Build Coastguard Worker> It might be desired, when decoding 3rd-party JSONs, to coerce `null` to a default value.
543*57b5a4a6SAndroid Build Coastguard Worker> The corresponding feature is explained in the [Coercing input values](json.md#coercing-input-values) section.
544*57b5a4a6SAndroid Build Coastguard Worker
545*57b5a4a6SAndroid Build Coastguard Worker### Referenced objects
546*57b5a4a6SAndroid Build Coastguard Worker
547*57b5a4a6SAndroid Build Coastguard WorkerSerializable classes can reference other classes in their serializable properties.
548*57b5a4a6SAndroid Build Coastguard WorkerThe referenced classes must be also marked as `@Serializable`.
549*57b5a4a6SAndroid Build Coastguard Worker
550*57b5a4a6SAndroid Build Coastguard Worker```kotlin
551*57b5a4a6SAndroid Build Coastguard Worker@Serializable
552*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val owner: User)
553*57b5a4a6SAndroid Build Coastguard Worker
554*57b5a4a6SAndroid Build Coastguard Worker@Serializable
555*57b5a4a6SAndroid Build Coastguard Workerclass User(val name: String)
556*57b5a4a6SAndroid Build Coastguard Worker
557*57b5a4a6SAndroid Build Coastguard Workerfun main() {
558*57b5a4a6SAndroid Build Coastguard Worker    val owner = User("kotlin")
559*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", owner)
560*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
561*57b5a4a6SAndroid Build Coastguard Worker}
562*57b5a4a6SAndroid Build Coastguard Worker```
563*57b5a4a6SAndroid Build Coastguard Worker
564*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-13.kt).
565*57b5a4a6SAndroid Build Coastguard Worker
566*57b5a4a6SAndroid Build Coastguard WorkerWhen encoded to JSON it results in a nested JSON object.
567*57b5a4a6SAndroid Build Coastguard Worker
568*57b5a4a6SAndroid Build Coastguard Worker```text
569*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","owner":{"name":"kotlin"}}
570*57b5a4a6SAndroid Build Coastguard Worker```
571*57b5a4a6SAndroid Build Coastguard Worker
572*57b5a4a6SAndroid Build Coastguard Worker> References to non-serializable classes can be marked as [Transient properties](#transient-properties), or a
573*57b5a4a6SAndroid Build Coastguard Worker> custom serializer can be provided for them as shown in the [Serializers](serializers.md) chapter.
574*57b5a4a6SAndroid Build Coastguard Worker
575*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
576*57b5a4a6SAndroid Build Coastguard Worker
577*57b5a4a6SAndroid Build Coastguard Worker### No compression of repeated references
578*57b5a4a6SAndroid Build Coastguard Worker
579*57b5a4a6SAndroid Build Coastguard WorkerKotlin Serialization is designed for encoding and decoding of plain data. It does not support reconstruction
580*57b5a4a6SAndroid Build Coastguard Workerof arbitrary object graphs with repeated object references. For example, let us try to serialize an object
581*57b5a4a6SAndroid Build Coastguard Workerthat references the same `owner` instance twice.
582*57b5a4a6SAndroid Build Coastguard Worker
583*57b5a4a6SAndroid Build Coastguard Worker```kotlin
584*57b5a4a6SAndroid Build Coastguard Worker@Serializable
585*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val owner: User, val maintainer: User)
586*57b5a4a6SAndroid Build Coastguard Worker
587*57b5a4a6SAndroid Build Coastguard Worker@Serializable
588*57b5a4a6SAndroid Build Coastguard Workerclass User(val name: String)
589*57b5a4a6SAndroid Build Coastguard Worker
590*57b5a4a6SAndroid Build Coastguard Workerfun main() {
591*57b5a4a6SAndroid Build Coastguard Worker    val owner = User("kotlin")
592*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", owner, owner)
593*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
594*57b5a4a6SAndroid Build Coastguard Worker}
595*57b5a4a6SAndroid Build Coastguard Worker```
596*57b5a4a6SAndroid Build Coastguard Worker
597*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-14.kt).
598*57b5a4a6SAndroid Build Coastguard Worker
599*57b5a4a6SAndroid Build Coastguard WorkerWe simply get the `owner` value encoded twice.
600*57b5a4a6SAndroid Build Coastguard Worker
601*57b5a4a6SAndroid Build Coastguard Worker```text
602*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","owner":{"name":"kotlin"},"maintainer":{"name":"kotlin"}}
603*57b5a4a6SAndroid Build Coastguard Worker```
604*57b5a4a6SAndroid Build Coastguard Worker
605*57b5a4a6SAndroid Build Coastguard Worker> Attempt to serialize a circular structure will result in stack overflow.
606*57b5a4a6SAndroid Build Coastguard Worker> You can use the [Transient properties](#transient-properties) to exclude some references from serialization.
607*57b5a4a6SAndroid Build Coastguard Worker
608*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
609*57b5a4a6SAndroid Build Coastguard Worker
610*57b5a4a6SAndroid Build Coastguard Worker### Generic classes
611*57b5a4a6SAndroid Build Coastguard Worker
612*57b5a4a6SAndroid Build Coastguard WorkerGeneric classes in Kotlin provide type-polymorphic behavior, which is enforced by Kotlin Serialization at
613*57b5a4a6SAndroid Build Coastguard Workercompile-time. For example, consider a generic serializable class `Box<T>`.
614*57b5a4a6SAndroid Build Coastguard Worker
615*57b5a4a6SAndroid Build Coastguard Worker```kotlin
616*57b5a4a6SAndroid Build Coastguard Worker@Serializable
617*57b5a4a6SAndroid Build Coastguard Workerclass Box<T>(val contents: T)
618*57b5a4a6SAndroid Build Coastguard Worker```
619*57b5a4a6SAndroid Build Coastguard Worker
620*57b5a4a6SAndroid Build Coastguard WorkerThe `Box<T>` class can be used with builtin types like `Int`, as well as with user-defined types like `Project`.
621*57b5a4a6SAndroid Build Coastguard Worker
622*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
623*57b5a4a6SAndroid Build Coastguard Worker
624*57b5a4a6SAndroid Build Coastguard Worker@Serializable
625*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String)
626*57b5a4a6SAndroid Build Coastguard Worker-->
627*57b5a4a6SAndroid Build Coastguard Worker
628*57b5a4a6SAndroid Build Coastguard Worker```kotlin
629*57b5a4a6SAndroid Build Coastguard Worker@Serializable
630*57b5a4a6SAndroid Build Coastguard Workerclass Data(
631*57b5a4a6SAndroid Build Coastguard Worker    val a: Box<Int>,
632*57b5a4a6SAndroid Build Coastguard Worker    val b: Box<Project>
633*57b5a4a6SAndroid Build Coastguard Worker)
634*57b5a4a6SAndroid Build Coastguard Worker
635*57b5a4a6SAndroid Build Coastguard Workerfun main() {
636*57b5a4a6SAndroid Build Coastguard Worker    val data = Data(Box(42), Box(Project("kotlinx.serialization", "Kotlin")))
637*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
638*57b5a4a6SAndroid Build Coastguard Worker}
639*57b5a4a6SAndroid Build Coastguard Worker```
640*57b5a4a6SAndroid Build Coastguard Worker
641*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-15.kt).
642*57b5a4a6SAndroid Build Coastguard Worker
643*57b5a4a6SAndroid Build Coastguard WorkerThe actual type that we get in JSON depends on the actual compile-time type parameter that was specified for `Box`.
644*57b5a4a6SAndroid Build Coastguard Worker
645*57b5a4a6SAndroid Build Coastguard Worker```text
646*57b5a4a6SAndroid Build Coastguard Worker{"a":{"contents":42},"b":{"contents":{"name":"kotlinx.serialization","language":"Kotlin"}}}
647*57b5a4a6SAndroid Build Coastguard Worker```
648*57b5a4a6SAndroid Build Coastguard Worker
649*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
650*57b5a4a6SAndroid Build Coastguard Worker
651*57b5a4a6SAndroid Build Coastguard WorkerIf the actual generic type is not serializable a compile-time error will be produced.
652*57b5a4a6SAndroid Build Coastguard Worker
653*57b5a4a6SAndroid Build Coastguard Worker### Serial field names
654*57b5a4a6SAndroid Build Coastguard Worker
655*57b5a4a6SAndroid Build Coastguard WorkerThe names of the properties used in encoded representation, JSON in our examples, are the same as
656*57b5a4a6SAndroid Build Coastguard Workertheir names in the source code by default. The name that is used for serialization is called a _serial name_, and
657*57b5a4a6SAndroid Build Coastguard Workercan be changed using the [`@SerialName`][SerialName] annotation. For example, we can have a `language` property in
658*57b5a4a6SAndroid Build Coastguard Workerthe source with an abbreviated serial name.
659*57b5a4a6SAndroid Build Coastguard Worker
660*57b5a4a6SAndroid Build Coastguard Worker```kotlin
661*57b5a4a6SAndroid Build Coastguard Worker@Serializable
662*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, @SerialName("lang") val language: String)
663*57b5a4a6SAndroid Build Coastguard Worker
664*57b5a4a6SAndroid Build Coastguard Workerfun main() {
665*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin")
666*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
667*57b5a4a6SAndroid Build Coastguard Worker}
668*57b5a4a6SAndroid Build Coastguard Worker```
669*57b5a4a6SAndroid Build Coastguard Worker
670*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-classes-16.kt).
671*57b5a4a6SAndroid Build Coastguard Worker
672*57b5a4a6SAndroid Build Coastguard WorkerNow we see that an abbreviated name `lang` is used in the JSON output.
673*57b5a4a6SAndroid Build Coastguard Worker
674*57b5a4a6SAndroid Build Coastguard Worker```text
675*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","lang":"Kotlin"}
676*57b5a4a6SAndroid Build Coastguard Worker```
677*57b5a4a6SAndroid Build Coastguard Worker
678*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
679*57b5a4a6SAndroid Build Coastguard Worker
680*57b5a4a6SAndroid Build Coastguard Worker---
681*57b5a4a6SAndroid Build Coastguard Worker
682*57b5a4a6SAndroid Build Coastguard WorkerThe next chapter covers [Builtin classes](builtin-classes.md).
683*57b5a4a6SAndroid Build Coastguard Worker
684*57b5a4a6SAndroid Build Coastguard Worker<!-- stdlib references -->
685*57b5a4a6SAndroid Build Coastguard Worker[kotlin.jvm.Transient]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-transient/
686*57b5a4a6SAndroid Build Coastguard Worker
687*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-core -->
688*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
689*57b5a4a6SAndroid Build Coastguard Worker
690*57b5a4a6SAndroid Build Coastguard Worker[kotlinx.serialization.encodeToString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/encode-to-string.html
691*57b5a4a6SAndroid Build Coastguard Worker[Serializable]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
692*57b5a4a6SAndroid Build Coastguard Worker[kotlinx.serialization.decodeFromString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/decode-from-string.html
693*57b5a4a6SAndroid Build Coastguard Worker[Required]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-required/index.html
694*57b5a4a6SAndroid Build Coastguard Worker[Transient]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-transient/index.html
695*57b5a4a6SAndroid Build Coastguard Worker[EncodeDefault]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-encode-default/index.html
696*57b5a4a6SAndroid Build Coastguard Worker[EncodeDefault.Mode]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-encode-default/-mode/index.html
697*57b5a4a6SAndroid Build Coastguard Worker[SerialName]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
698*57b5a4a6SAndroid Build Coastguard Worker
699*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-json -->
700*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-json/kotlinx.serialization.json -->
701*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
702