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_—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_—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