xref: /aosp_15_r20/external/kotlinx.serialization/docs/json.md (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST_NAME JsonTest -->
2*57b5a4a6SAndroid Build Coastguard Worker
3*57b5a4a6SAndroid Build Coastguard Worker# JSON features
4*57b5a4a6SAndroid Build Coastguard Worker
5*57b5a4a6SAndroid Build Coastguard WorkerThis is the fifth chapter of the [Kotlin Serialization Guide](serialization-guide.md).
6*57b5a4a6SAndroid Build Coastguard WorkerIn this chapter, we'll walk through features of [JSON](https://www.json.org/json-en.html) serialization available in the [Json] class.
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* [Json configuration](#json-configuration)
13*57b5a4a6SAndroid Build Coastguard Worker  * [Pretty printing](#pretty-printing)
14*57b5a4a6SAndroid Build Coastguard Worker  * [Lenient parsing](#lenient-parsing)
15*57b5a4a6SAndroid Build Coastguard Worker  * [Ignoring unknown keys](#ignoring-unknown-keys)
16*57b5a4a6SAndroid Build Coastguard Worker  * [Alternative Json names](#alternative-json-names)
17*57b5a4a6SAndroid Build Coastguard Worker  * [Coercing input values](#coercing-input-values)
18*57b5a4a6SAndroid Build Coastguard Worker  * [Encoding defaults](#encoding-defaults)
19*57b5a4a6SAndroid Build Coastguard Worker  * [Explicit nulls](#explicit-nulls)
20*57b5a4a6SAndroid Build Coastguard Worker  * [Allowing structured map keys](#allowing-structured-map-keys)
21*57b5a4a6SAndroid Build Coastguard Worker  * [Allowing special floating-point values](#allowing-special-floating-point-values)
22*57b5a4a6SAndroid Build Coastguard Worker  * [Class discriminator for polymorphism](#class-discriminator-for-polymorphism)
23*57b5a4a6SAndroid Build Coastguard Worker  * [Class discriminator output mode](#class-discriminator-output-mode)
24*57b5a4a6SAndroid Build Coastguard Worker  * [Decoding enums in a case-insensitive manner](#decoding-enums-in-a-case-insensitive-manner)
25*57b5a4a6SAndroid Build Coastguard Worker  * [Global naming strategy](#global-naming-strategy)
26*57b5a4a6SAndroid Build Coastguard Worker* [Json elements](#json-elements)
27*57b5a4a6SAndroid Build Coastguard Worker  * [Parsing to Json element](#parsing-to-json-element)
28*57b5a4a6SAndroid Build Coastguard Worker  * [Types of Json elements](#types-of-json-elements)
29*57b5a4a6SAndroid Build Coastguard Worker  * [Json element builders](#json-element-builders)
30*57b5a4a6SAndroid Build Coastguard Worker  * [Decoding Json elements](#decoding-json-elements)
31*57b5a4a6SAndroid Build Coastguard Worker  * [Encoding literal Json content (experimental)](#encoding-literal-json-content-experimental)
32*57b5a4a6SAndroid Build Coastguard Worker    * [Serializing large decimal numbers](#serializing-large-decimal-numbers)
33*57b5a4a6SAndroid Build Coastguard Worker    * [Using `JsonUnquotedLiteral` to create a literal unquoted value of `null` is forbidden](#using-jsonunquotedliteral-to-create-a-literal-unquoted-value-of-null-is-forbidden)
34*57b5a4a6SAndroid Build Coastguard Worker* [Json transformations](#json-transformations)
35*57b5a4a6SAndroid Build Coastguard Worker  * [Array wrapping](#array-wrapping)
36*57b5a4a6SAndroid Build Coastguard Worker  * [Array unwrapping](#array-unwrapping)
37*57b5a4a6SAndroid Build Coastguard Worker  * [Manipulating default values](#manipulating-default-values)
38*57b5a4a6SAndroid Build Coastguard Worker  * [Content-based polymorphic deserialization](#content-based-polymorphic-deserialization)
39*57b5a4a6SAndroid Build Coastguard Worker  * [Under the hood (experimental)](#under-the-hood-experimental)
40*57b5a4a6SAndroid Build Coastguard Worker  * [Maintaining custom JSON attributes](#maintaining-custom-json-attributes)
41*57b5a4a6SAndroid Build Coastguard Worker
42*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
43*57b5a4a6SAndroid Build Coastguard Worker
44*57b5a4a6SAndroid Build Coastguard Worker## Json configuration
45*57b5a4a6SAndroid Build Coastguard Worker
46*57b5a4a6SAndroid Build Coastguard WorkerThe default [Json] implementation is quite strict with respect to invalid inputs. It enforces Kotlin type safety and
47*57b5a4a6SAndroid Build Coastguard Workerrestricts Kotlin values that can be serialized so that the resulting JSON representations are standard.
48*57b5a4a6SAndroid Build Coastguard WorkerMany non-standard JSON features are supported by creating a custom instance of a JSON _format_.
49*57b5a4a6SAndroid Build Coastguard Worker
50*57b5a4a6SAndroid Build Coastguard WorkerTo use a custom JSON format configuration, create your own [Json] class instance from an existing
51*57b5a4a6SAndroid Build Coastguard Workerinstance, such as a default `Json` object, using the [Json()] builder function. Specify parameter values
52*57b5a4a6SAndroid Build Coastguard Workerin the parentheses via the [JsonBuilder] DSL. The resulting `Json` format instance is immutable and thread-safe;
53*57b5a4a6SAndroid Build Coastguard Workerit can be simply stored in a top-level property.
54*57b5a4a6SAndroid Build Coastguard Worker
55*57b5a4a6SAndroid Build Coastguard Worker> We recommend that you store and reuse custom instances of formats for performance reasons because format implementations
56*57b5a4a6SAndroid Build Coastguard Worker> may cache format-specific additional information about the classes they serialize.
57*57b5a4a6SAndroid Build Coastguard Worker
58*57b5a4a6SAndroid Build Coastguard WorkerThis chapter shows configuration features that [Json] supports.
59*57b5a4a6SAndroid Build Coastguard Worker
60*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE .*-json-.*
61*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.*
62*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.json.*
63*57b5a4a6SAndroid Build Coastguard Worker-->
64*57b5a4a6SAndroid Build Coastguard Worker
65*57b5a4a6SAndroid Build Coastguard Worker### Pretty printing
66*57b5a4a6SAndroid Build Coastguard Worker
67*57b5a4a6SAndroid Build Coastguard WorkerBy default, the [Json] output is a single line. You can configure it to pretty print the output (that is, add indentations
68*57b5a4a6SAndroid Build Coastguard Workerand line breaks for better readability) by setting the [prettyPrint][JsonBuilder.prettyPrint] property to `true`:
69*57b5a4a6SAndroid Build Coastguard Worker
70*57b5a4a6SAndroid Build Coastguard Worker```kotlin
71*57b5a4a6SAndroid Build Coastguard Workerval format = Json { prettyPrint = true }
72*57b5a4a6SAndroid Build Coastguard Worker
73*57b5a4a6SAndroid Build Coastguard Worker@Serializable
74*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String)
75*57b5a4a6SAndroid Build Coastguard Worker
76*57b5a4a6SAndroid Build Coastguard Workerfun main() {
77*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin")
78*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
79*57b5a4a6SAndroid Build Coastguard Worker}
80*57b5a4a6SAndroid Build Coastguard Worker```
81*57b5a4a6SAndroid Build Coastguard Worker
82*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-01.kt).
83*57b5a4a6SAndroid Build Coastguard Worker
84*57b5a4a6SAndroid Build Coastguard WorkerIt gives the following nice result:
85*57b5a4a6SAndroid Build Coastguard Worker
86*57b5a4a6SAndroid Build Coastguard Worker```text
87*57b5a4a6SAndroid Build Coastguard Worker{
88*57b5a4a6SAndroid Build Coastguard Worker    "name": "kotlinx.serialization",
89*57b5a4a6SAndroid Build Coastguard Worker    "language": "Kotlin"
90*57b5a4a6SAndroid Build Coastguard Worker}
91*57b5a4a6SAndroid Build Coastguard Worker```
92*57b5a4a6SAndroid Build Coastguard Worker
93*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
94*57b5a4a6SAndroid Build Coastguard Worker
95*57b5a4a6SAndroid Build Coastguard Worker### Lenient parsing
96*57b5a4a6SAndroid Build Coastguard Worker
97*57b5a4a6SAndroid Build Coastguard WorkerBy default, [Json] parser enforces various JSON restrictions to be as specification-compliant as possible
98*57b5a4a6SAndroid Build Coastguard Worker(see [RFC-4627]). Particularly, keys and string literals must be quoted. Those restrictions can be relaxed with
99*57b5a4a6SAndroid Build Coastguard Workerthe [isLenient][JsonBuilder.isLenient] property. With `isLenient = true`, you can parse quite freely-formatted data:
100*57b5a4a6SAndroid Build Coastguard Worker
101*57b5a4a6SAndroid Build Coastguard Worker```kotlin
102*57b5a4a6SAndroid Build Coastguard Workerval format = Json { isLenient = true }
103*57b5a4a6SAndroid Build Coastguard Worker
104*57b5a4a6SAndroid Build Coastguard Workerenum class Status { SUPPORTED }
105*57b5a4a6SAndroid Build Coastguard Worker
106*57b5a4a6SAndroid Build Coastguard Worker@Serializable
107*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val status: Status, val votes: Int)
108*57b5a4a6SAndroid Build Coastguard Worker
109*57b5a4a6SAndroid Build Coastguard Workerfun main() {
110*57b5a4a6SAndroid Build Coastguard Worker    val data = format.decodeFromString<Project>("""
111*57b5a4a6SAndroid Build Coastguard Worker        {
112*57b5a4a6SAndroid Build Coastguard Worker            name   : kotlinx.serialization,
113*57b5a4a6SAndroid Build Coastguard Worker            status : SUPPORTED,
114*57b5a4a6SAndroid Build Coastguard Worker            votes  : "9000"
115*57b5a4a6SAndroid Build Coastguard Worker        }
116*57b5a4a6SAndroid Build Coastguard Worker    """)
117*57b5a4a6SAndroid Build Coastguard Worker    println(data)
118*57b5a4a6SAndroid Build Coastguard Worker}
119*57b5a4a6SAndroid Build Coastguard Worker```
120*57b5a4a6SAndroid Build Coastguard Worker
121*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-02.kt).
122*57b5a4a6SAndroid Build Coastguard Worker
123*57b5a4a6SAndroid Build Coastguard WorkerYou get the object, even though all keys of the source JSON, string, and enum values are unquoted, while an
124*57b5a4a6SAndroid Build Coastguard Workerinteger is quoted:
125*57b5a4a6SAndroid Build Coastguard Worker
126*57b5a4a6SAndroid Build Coastguard Worker```text
127*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, status=SUPPORTED, votes=9000)
128*57b5a4a6SAndroid Build Coastguard Worker```
129*57b5a4a6SAndroid Build Coastguard Worker
130*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
131*57b5a4a6SAndroid Build Coastguard Worker
132*57b5a4a6SAndroid Build Coastguard Worker### Ignoring unknown keys
133*57b5a4a6SAndroid Build Coastguard Worker
134*57b5a4a6SAndroid Build Coastguard WorkerJSON format is often used to read the output of third-party services or in other dynamic environments where
135*57b5a4a6SAndroid Build Coastguard Workernew properties can be added during the API evolution. By default, unknown keys encountered during deserialization produce an error.
136*57b5a4a6SAndroid Build Coastguard WorkerYou can avoid this and just ignore such keys by setting the [ignoreUnknownKeys][JsonBuilder.ignoreUnknownKeys] property
137*57b5a4a6SAndroid Build Coastguard Workerto `true`:
138*57b5a4a6SAndroid Build Coastguard Worker
139*57b5a4a6SAndroid Build Coastguard Worker```kotlin
140*57b5a4a6SAndroid Build Coastguard Workerval format = Json { ignoreUnknownKeys = true }
141*57b5a4a6SAndroid Build Coastguard Worker
142*57b5a4a6SAndroid Build Coastguard Worker@Serializable
143*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String)
144*57b5a4a6SAndroid Build Coastguard Worker
145*57b5a4a6SAndroid Build Coastguard Workerfun main() {
146*57b5a4a6SAndroid Build Coastguard Worker    val data = format.decodeFromString<Project>("""
147*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":"Kotlin"}
148*57b5a4a6SAndroid Build Coastguard Worker    """)
149*57b5a4a6SAndroid Build Coastguard Worker    println(data)
150*57b5a4a6SAndroid Build Coastguard Worker}
151*57b5a4a6SAndroid Build Coastguard Worker```
152*57b5a4a6SAndroid Build Coastguard Worker
153*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-03.kt).
154*57b5a4a6SAndroid Build Coastguard Worker
155*57b5a4a6SAndroid Build Coastguard WorkerIt decodes the object despite the fact that the `Project` class doesn't have the `language` property:
156*57b5a4a6SAndroid Build Coastguard Worker
157*57b5a4a6SAndroid Build Coastguard Worker```text
158*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization)
159*57b5a4a6SAndroid Build Coastguard Worker```
160*57b5a4a6SAndroid Build Coastguard Worker
161*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
162*57b5a4a6SAndroid Build Coastguard Worker
163*57b5a4a6SAndroid Build Coastguard Worker### Alternative Json names
164*57b5a4a6SAndroid Build Coastguard Worker
165*57b5a4a6SAndroid Build Coastguard WorkerIt's not a rare case when JSON fields are renamed due to a schema version change.
166*57b5a4a6SAndroid Build Coastguard WorkerYou can use the [`@SerialName` annotation](basic-serialization.md#serial-field-names) to change the name of a JSON field,
167*57b5a4a6SAndroid Build Coastguard Workerbut such renaming blocks the ability to decode data with the old name.
168*57b5a4a6SAndroid Build Coastguard WorkerTo support multiple JSON names for the one Kotlin property, there is the [JsonNames] annotation:
169*57b5a4a6SAndroid Build Coastguard Worker
170*57b5a4a6SAndroid Build Coastguard Worker```kotlin
171*57b5a4a6SAndroid Build Coastguard Worker@Serializable
172*57b5a4a6SAndroid Build Coastguard Workerdata class Project(@JsonNames("title") val name: String)
173*57b5a4a6SAndroid Build Coastguard Worker
174*57b5a4a6SAndroid Build Coastguard Workerfun main() {
175*57b5a4a6SAndroid Build Coastguard Worker  val project = Json.decodeFromString<Project>("""{"name":"kotlinx.serialization"}""")
176*57b5a4a6SAndroid Build Coastguard Worker  println(project)
177*57b5a4a6SAndroid Build Coastguard Worker  val oldProject = Json.decodeFromString<Project>("""{"title":"kotlinx.coroutines"}""")
178*57b5a4a6SAndroid Build Coastguard Worker  println(oldProject)
179*57b5a4a6SAndroid Build Coastguard Worker}
180*57b5a4a6SAndroid Build Coastguard Worker```
181*57b5a4a6SAndroid Build Coastguard Worker
182*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-04.kt).
183*57b5a4a6SAndroid Build Coastguard Worker
184*57b5a4a6SAndroid Build Coastguard WorkerAs you can see, both `name` and `title` Json fields correspond to `name` property:
185*57b5a4a6SAndroid Build Coastguard Worker
186*57b5a4a6SAndroid Build Coastguard Worker```text
187*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization)
188*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.coroutines)
189*57b5a4a6SAndroid Build Coastguard Worker```
190*57b5a4a6SAndroid Build Coastguard Worker
191*57b5a4a6SAndroid Build Coastguard WorkerSupport for [JsonNames] annotation is controlled by the [JsonBuilder.useAlternativeNames] flag.
192*57b5a4a6SAndroid Build Coastguard WorkerUnlike most of the configuration flags, this one is enabled by default and does not need attention
193*57b5a4a6SAndroid Build Coastguard Workerunless you want to do some fine-tuning.
194*57b5a4a6SAndroid Build Coastguard Worker
195*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
196*57b5a4a6SAndroid Build Coastguard Worker
197*57b5a4a6SAndroid Build Coastguard Worker### Coercing input values
198*57b5a4a6SAndroid Build Coastguard Worker
199*57b5a4a6SAndroid Build Coastguard WorkerJSON formats that from third parties can evolve, sometimes changing the field types.
200*57b5a4a6SAndroid Build Coastguard WorkerThis can lead to exceptions during decoding when the actual values do not match the expected values.
201*57b5a4a6SAndroid Build Coastguard WorkerThe default [Json] implementation is strict with respect to input types as was demonstrated in
202*57b5a4a6SAndroid Build Coastguard Workerthe [Type safety is enforced](basic-serialization.md#type-safety-is-enforced) section. You can relax this restriction
203*57b5a4a6SAndroid Build Coastguard Workerusing the [coerceInputValues][JsonBuilder.coerceInputValues] property.
204*57b5a4a6SAndroid Build Coastguard Worker
205*57b5a4a6SAndroid Build Coastguard WorkerThis property only affects decoding. It treats a limited subset of invalid input values as if the
206*57b5a4a6SAndroid Build Coastguard Workercorresponding property was missing and uses the default value of the corresponding property instead.
207*57b5a4a6SAndroid Build Coastguard WorkerThe current list of supported invalid values is:
208*57b5a4a6SAndroid Build Coastguard Worker
209*57b5a4a6SAndroid Build Coastguard Worker* `null` inputs for non-nullable types
210*57b5a4a6SAndroid Build Coastguard Worker* unknown values for enums
211*57b5a4a6SAndroid Build Coastguard Worker
212*57b5a4a6SAndroid Build Coastguard Worker> This list may be expanded in the future, so that [Json] instance configured with this property becomes even more
213*57b5a4a6SAndroid Build Coastguard Worker> permissive to invalid value in the input, replacing them with defaults.
214*57b5a4a6SAndroid Build Coastguard Worker
215*57b5a4a6SAndroid Build Coastguard WorkerSee the example from the [Type safety is enforced](basic-serialization.md#type-safety-is-enforced) section:
216*57b5a4a6SAndroid Build Coastguard Worker
217*57b5a4a6SAndroid Build Coastguard Worker```kotlin
218*57b5a4a6SAndroid Build Coastguard Workerval format = Json { coerceInputValues = true }
219*57b5a4a6SAndroid Build Coastguard Worker
220*57b5a4a6SAndroid Build Coastguard Worker@Serializable
221*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String = "Kotlin")
222*57b5a4a6SAndroid Build Coastguard Worker
223*57b5a4a6SAndroid Build Coastguard Workerfun main() {
224*57b5a4a6SAndroid Build Coastguard Worker    val data = format.decodeFromString<Project>("""
225*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":null}
226*57b5a4a6SAndroid Build Coastguard Worker    """)
227*57b5a4a6SAndroid Build Coastguard Worker    println(data)
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-json-05.kt).
232*57b5a4a6SAndroid Build Coastguard Worker
233*57b5a4a6SAndroid Build Coastguard WorkerThe invalid `null` value for the `language` property was coerced into the default value:
234*57b5a4a6SAndroid Build Coastguard Worker
235*57b5a4a6SAndroid Build Coastguard Worker```text
236*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin)
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
242*57b5a4a6SAndroid Build Coastguard Worker### Encoding defaults
243*57b5a4a6SAndroid Build Coastguard Worker
244*57b5a4a6SAndroid Build Coastguard WorkerDefault values of properties are not encoded by default because they will be assigned to missing fields during decoding anyway.
245*57b5a4a6SAndroid Build Coastguard WorkerSee the [Defaults are not encoded](basic-serialization.md#defaults-are-not-encoded-by-default) section for details and an example.
246*57b5a4a6SAndroid Build Coastguard WorkerThis is especially useful for nullable properties with null defaults and avoids writing the corresponding null values.
247*57b5a4a6SAndroid Build Coastguard WorkerThe default behavior can be changed by setting the [encodeDefaults][JsonBuilder.encodeDefaults] property to `true`:
248*57b5a4a6SAndroid Build Coastguard Worker
249*57b5a4a6SAndroid Build Coastguard Worker```kotlin
250*57b5a4a6SAndroid Build Coastguard Workerval format = Json { encodeDefaults = true }
251*57b5a4a6SAndroid Build Coastguard Worker
252*57b5a4a6SAndroid Build Coastguard Worker@Serializable
253*57b5a4a6SAndroid Build Coastguard Workerclass Project(
254*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
255*57b5a4a6SAndroid Build Coastguard Worker    val language: String = "Kotlin",
256*57b5a4a6SAndroid Build Coastguard Worker    val website: String? = null
257*57b5a4a6SAndroid Build Coastguard Worker)
258*57b5a4a6SAndroid Build Coastguard Worker
259*57b5a4a6SAndroid Build Coastguard Workerfun main() {
260*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization")
261*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
262*57b5a4a6SAndroid Build Coastguard Worker}
263*57b5a4a6SAndroid Build Coastguard Worker```
264*57b5a4a6SAndroid Build Coastguard Worker
265*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-06.kt).
266*57b5a4a6SAndroid Build Coastguard Worker
267*57b5a4a6SAndroid Build Coastguard WorkerIt produces the following output which encodes all the property values including the default ones:
268*57b5a4a6SAndroid Build Coastguard Worker
269*57b5a4a6SAndroid Build Coastguard Worker```text
270*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","language":"Kotlin","website":null}
271*57b5a4a6SAndroid Build Coastguard Worker```
272*57b5a4a6SAndroid Build Coastguard Worker
273*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
274*57b5a4a6SAndroid Build Coastguard Worker
275*57b5a4a6SAndroid Build Coastguard Worker### Explicit nulls
276*57b5a4a6SAndroid Build Coastguard Worker
277*57b5a4a6SAndroid Build Coastguard WorkerBy default, all `null` values are encoded into JSON strings, but in some cases you may want to omit them.
278*57b5a4a6SAndroid Build Coastguard WorkerThe encoding of `null` values can be controlled with the [explicitNulls][JsonBuilder.explicitNulls] property.
279*57b5a4a6SAndroid Build Coastguard Worker
280*57b5a4a6SAndroid Build Coastguard WorkerIf you set property to `false`, fields with `null` values are not encoded into JSON even if the property does not have a
281*57b5a4a6SAndroid Build Coastguard Workerdefault `null` value. When decoding such JSON, the absence of a property value is treated as `null` for nullable properties
282*57b5a4a6SAndroid Build Coastguard Workerwithout a default value.
283*57b5a4a6SAndroid Build Coastguard Worker
284*57b5a4a6SAndroid Build Coastguard Worker```kotlin
285*57b5a4a6SAndroid Build Coastguard Workerval format = Json { explicitNulls = false }
286*57b5a4a6SAndroid Build Coastguard Worker
287*57b5a4a6SAndroid Build Coastguard Worker@Serializable
288*57b5a4a6SAndroid Build Coastguard Workerdata class Project(
289*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
290*57b5a4a6SAndroid Build Coastguard Worker    val language: String,
291*57b5a4a6SAndroid Build Coastguard Worker    val version: String? = "1.2.2",
292*57b5a4a6SAndroid Build Coastguard Worker    val website: String?,
293*57b5a4a6SAndroid Build Coastguard Worker    val description: String? = null
294*57b5a4a6SAndroid Build Coastguard Worker)
295*57b5a4a6SAndroid Build Coastguard Worker
296*57b5a4a6SAndroid Build Coastguard Workerfun main() {
297*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin", null, null, null)
298*57b5a4a6SAndroid Build Coastguard Worker    val json = format.encodeToString(data)
299*57b5a4a6SAndroid Build Coastguard Worker    println(json)
300*57b5a4a6SAndroid Build Coastguard Worker    println(format.decodeFromString<Project>(json))
301*57b5a4a6SAndroid Build Coastguard Worker}
302*57b5a4a6SAndroid Build Coastguard Worker```
303*57b5a4a6SAndroid Build Coastguard Worker
304*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-07.kt).
305*57b5a4a6SAndroid Build Coastguard Worker
306*57b5a4a6SAndroid Build Coastguard WorkerAs you can see, `version`, `website` and `description` fields are not present in output JSON on the first line.
307*57b5a4a6SAndroid Build Coastguard WorkerAfter decoding, the missing nullable property `website` without a default values has received a `null` value,
308*57b5a4a6SAndroid Build Coastguard Workerwhile nullable properties `version` and `description` are filled with their default values:
309*57b5a4a6SAndroid Build Coastguard Worker
310*57b5a4a6SAndroid Build Coastguard Worker```text
311*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","language":"Kotlin"}
312*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin, version=1.2.2, website=null, description=null)
313*57b5a4a6SAndroid Build Coastguard Worker```
314*57b5a4a6SAndroid Build Coastguard Worker
315*57b5a4a6SAndroid Build Coastguard Worker`explicitNulls` is `true` by default as it is the default behavior across different versions of the library.
316*57b5a4a6SAndroid Build Coastguard Worker
317*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
318*57b5a4a6SAndroid Build Coastguard Worker
319*57b5a4a6SAndroid Build Coastguard Worker### Allowing structured map keys
320*57b5a4a6SAndroid Build Coastguard Worker
321*57b5a4a6SAndroid Build Coastguard WorkerJSON format does not natively support the concept of a map with structured keys. Keys in JSON objects
322*57b5a4a6SAndroid Build Coastguard Workerare strings and can be used to represent only primitives or enums by default.
323*57b5a4a6SAndroid Build Coastguard WorkerYou can enable non-standard support for structured keys with
324*57b5a4a6SAndroid Build Coastguard Workerthe [allowStructuredMapKeys][JsonBuilder.allowStructuredMapKeys] property.
325*57b5a4a6SAndroid Build Coastguard Worker
326*57b5a4a6SAndroid Build Coastguard WorkerThis is how you can serialize a map with keys of a user-defined class:
327*57b5a4a6SAndroid Build Coastguard Worker
328*57b5a4a6SAndroid Build Coastguard Worker```kotlin
329*57b5a4a6SAndroid Build Coastguard Workerval format = Json { allowStructuredMapKeys = true }
330*57b5a4a6SAndroid Build Coastguard Worker
331*57b5a4a6SAndroid Build Coastguard Worker@Serializable
332*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String)
333*57b5a4a6SAndroid Build Coastguard Worker
334*57b5a4a6SAndroid Build Coastguard Workerfun main() {
335*57b5a4a6SAndroid Build Coastguard Worker    val map = mapOf(
336*57b5a4a6SAndroid Build Coastguard Worker        Project("kotlinx.serialization") to "Serialization",
337*57b5a4a6SAndroid Build Coastguard Worker        Project("kotlinx.coroutines") to "Coroutines"
338*57b5a4a6SAndroid Build Coastguard Worker    )
339*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(map))
340*57b5a4a6SAndroid Build Coastguard Worker}
341*57b5a4a6SAndroid Build Coastguard Worker```
342*57b5a4a6SAndroid Build Coastguard Worker
343*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-08.kt).
344*57b5a4a6SAndroid Build Coastguard Worker
345*57b5a4a6SAndroid Build Coastguard WorkerThe map with structured keys gets represented as JSON array with the following items: `[key1, value1, key2, value2,...]`.
346*57b5a4a6SAndroid Build Coastguard Worker
347*57b5a4a6SAndroid Build Coastguard Worker```text
348*57b5a4a6SAndroid Build Coastguard Worker[{"name":"kotlinx.serialization"},"Serialization",{"name":"kotlinx.coroutines"},"Coroutines"]
349*57b5a4a6SAndroid Build Coastguard Worker```
350*57b5a4a6SAndroid Build Coastguard Worker
351*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
352*57b5a4a6SAndroid Build Coastguard Worker
353*57b5a4a6SAndroid Build Coastguard Worker### Allowing special floating-point values
354*57b5a4a6SAndroid Build Coastguard Worker
355*57b5a4a6SAndroid Build Coastguard WorkerBy default, special floating-point values like [Double.NaN] and infinities are not supported in JSON because
356*57b5a4a6SAndroid Build Coastguard Workerthe JSON specification prohibits it.
357*57b5a4a6SAndroid Build Coastguard WorkerYou can enable their encoding using the [allowSpecialFloatingPointValues][JsonBuilder.allowSpecialFloatingPointValues]
358*57b5a4a6SAndroid Build Coastguard Workerproperty:
359*57b5a4a6SAndroid Build Coastguard Worker
360*57b5a4a6SAndroid Build Coastguard Worker```kotlin
361*57b5a4a6SAndroid Build Coastguard Workerval format = Json { allowSpecialFloatingPointValues = true }
362*57b5a4a6SAndroid Build Coastguard Worker
363*57b5a4a6SAndroid Build Coastguard Worker@Serializable
364*57b5a4a6SAndroid Build Coastguard Workerclass Data(
365*57b5a4a6SAndroid Build Coastguard Worker    val value: Double
366*57b5a4a6SAndroid Build Coastguard Worker)
367*57b5a4a6SAndroid Build Coastguard Worker
368*57b5a4a6SAndroid Build Coastguard Workerfun main() {
369*57b5a4a6SAndroid Build Coastguard Worker    val data = Data(Double.NaN)
370*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
371*57b5a4a6SAndroid Build Coastguard Worker}
372*57b5a4a6SAndroid Build Coastguard Worker```
373*57b5a4a6SAndroid Build Coastguard Worker
374*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-09.kt).
375*57b5a4a6SAndroid Build Coastguard Worker
376*57b5a4a6SAndroid Build Coastguard WorkerThis example produces the following non-stardard JSON output, yet it is a widely used encoding for
377*57b5a4a6SAndroid Build Coastguard Workerspecial values in JVM world:
378*57b5a4a6SAndroid Build Coastguard Worker
379*57b5a4a6SAndroid Build Coastguard Worker```text
380*57b5a4a6SAndroid Build Coastguard Worker{"value":NaN}
381*57b5a4a6SAndroid Build Coastguard Worker```
382*57b5a4a6SAndroid Build Coastguard Worker
383*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
384*57b5a4a6SAndroid Build Coastguard Worker
385*57b5a4a6SAndroid Build Coastguard Worker### Class discriminator for polymorphism
386*57b5a4a6SAndroid Build Coastguard Worker
387*57b5a4a6SAndroid Build Coastguard WorkerA key name that specifies a type when you have a polymorphic data can be specified
388*57b5a4a6SAndroid Build Coastguard Workerin the [classDiscriminator][JsonBuilder.classDiscriminator] property:
389*57b5a4a6SAndroid Build Coastguard Worker
390*57b5a4a6SAndroid Build Coastguard Worker```kotlin
391*57b5a4a6SAndroid Build Coastguard Workerval format = Json { classDiscriminator = "#class" }
392*57b5a4a6SAndroid Build Coastguard Worker
393*57b5a4a6SAndroid Build Coastguard Worker@Serializable
394*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
395*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
396*57b5a4a6SAndroid Build Coastguard Worker}
397*57b5a4a6SAndroid Build Coastguard Worker
398*57b5a4a6SAndroid Build Coastguard Worker@Serializable
399*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
400*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
401*57b5a4a6SAndroid Build Coastguard Worker
402*57b5a4a6SAndroid Build Coastguard Workerfun main() {
403*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
404*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(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-json-10.kt).
409*57b5a4a6SAndroid Build Coastguard Worker
410*57b5a4a6SAndroid Build Coastguard WorkerIn combination with an explicitly specified [SerialName] of the class it provides full
411*57b5a4a6SAndroid Build Coastguard Workercontrol over the resulting JSON object:
412*57b5a4a6SAndroid Build Coastguard Worker
413*57b5a4a6SAndroid Build Coastguard Worker```text
414*57b5a4a6SAndroid Build Coastguard Worker{"#class":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
415*57b5a4a6SAndroid Build Coastguard Worker```
416*57b5a4a6SAndroid Build Coastguard Worker
417*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
418*57b5a4a6SAndroid Build Coastguard Worker
419*57b5a4a6SAndroid Build Coastguard WorkerIt is also possible to specify different class discriminators for different hierarchies. Instead of Json instance property, use [JsonClassDiscriminator] annotation directly on base serializable class:
420*57b5a4a6SAndroid Build Coastguard Worker
421*57b5a4a6SAndroid Build Coastguard Worker```kotlin
422*57b5a4a6SAndroid Build Coastguard Worker@Serializable
423*57b5a4a6SAndroid Build Coastguard Worker@JsonClassDiscriminator("message_type")
424*57b5a4a6SAndroid Build Coastguard Workersealed class Base
425*57b5a4a6SAndroid Build Coastguard Worker```
426*57b5a4a6SAndroid Build Coastguard Worker
427*57b5a4a6SAndroid Build Coastguard WorkerThis annotation is _inheritable_, so all subclasses of `Base` will have the same discriminator:
428*57b5a4a6SAndroid Build Coastguard Worker
429*57b5a4a6SAndroid Build Coastguard Worker```kotlin
430*57b5a4a6SAndroid Build Coastguard Worker@Serializable // Class discriminator is inherited from Base
431*57b5a4a6SAndroid Build Coastguard Workersealed class ErrorClass: Base()
432*57b5a4a6SAndroid Build Coastguard Worker```
433*57b5a4a6SAndroid Build Coastguard Worker
434*57b5a4a6SAndroid Build Coastguard Worker> To learn more about inheritable serial annotations, see documentation for [InheritableSerialInfo].
435*57b5a4a6SAndroid Build Coastguard Worker
436*57b5a4a6SAndroid Build Coastguard WorkerNote that it is not possible to explicitly specify different class discriminators in subclasses of `Base`. Only hierarchies with empty intersections can have different discriminators.
437*57b5a4a6SAndroid Build Coastguard Worker
438*57b5a4a6SAndroid Build Coastguard WorkerDiscriminator specified in the annotation has priority over discriminator in Json configuration:
439*57b5a4a6SAndroid Build Coastguard Worker
440*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
441*57b5a4a6SAndroid Build Coastguard Worker
442*57b5a4a6SAndroid Build Coastguard Worker@Serializable
443*57b5a4a6SAndroid Build Coastguard Workerdata class Message(val message: Base, val error: ErrorClass?)
444*57b5a4a6SAndroid Build Coastguard Worker
445*57b5a4a6SAndroid Build Coastguard Worker@Serializable
446*57b5a4a6SAndroid Build Coastguard Worker@SerialName("my.app.BaseMessage")
447*57b5a4a6SAndroid Build Coastguard Workerdata class BaseMessage(val message: String) : Base()
448*57b5a4a6SAndroid Build Coastguard Worker
449*57b5a4a6SAndroid Build Coastguard Worker@Serializable
450*57b5a4a6SAndroid Build Coastguard Worker@SerialName("my.app.GenericError")
451*57b5a4a6SAndroid Build Coastguard Workerdata class GenericError(@SerialName("error_code") val errorCode: Int) : ErrorClass()
452*57b5a4a6SAndroid Build Coastguard Worker-->
453*57b5a4a6SAndroid Build Coastguard Worker
454*57b5a4a6SAndroid Build Coastguard Worker```kotlin
455*57b5a4a6SAndroid Build Coastguard Worker
456*57b5a4a6SAndroid Build Coastguard Workerval format = Json { classDiscriminator = "#class" }
457*57b5a4a6SAndroid Build Coastguard Worker
458*57b5a4a6SAndroid Build Coastguard Workerfun main() {
459*57b5a4a6SAndroid Build Coastguard Worker    val data = Message(BaseMessage("not found"), GenericError(404))
460*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
461*57b5a4a6SAndroid Build Coastguard Worker}
462*57b5a4a6SAndroid Build Coastguard Worker```
463*57b5a4a6SAndroid Build Coastguard Worker
464*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-11.kt).
465*57b5a4a6SAndroid Build Coastguard Worker
466*57b5a4a6SAndroid Build Coastguard WorkerAs you can see, discriminator from the `Base` class is used:
467*57b5a4a6SAndroid Build Coastguard Worker
468*57b5a4a6SAndroid Build Coastguard Worker```text
469*57b5a4a6SAndroid Build Coastguard Worker{"message":{"message_type":"my.app.BaseMessage","message":"not found"},"error":{"message_type":"my.app.GenericError","error_code":404}}
470*57b5a4a6SAndroid Build Coastguard Worker```
471*57b5a4a6SAndroid Build Coastguard Worker
472*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
473*57b5a4a6SAndroid Build Coastguard Worker
474*57b5a4a6SAndroid Build Coastguard Worker### Class discriminator output mode
475*57b5a4a6SAndroid Build Coastguard Worker
476*57b5a4a6SAndroid Build Coastguard WorkerClass discriminator provides information for serializing and deserializing [polymorphic class hierarchies](polymorphism.md#sealed-classes).
477*57b5a4a6SAndroid Build Coastguard WorkerAs shown above, it is only added for polymorphic classes by default.
478*57b5a4a6SAndroid Build Coastguard WorkerIn case you want to encode more or less information for various third party APIs about types in the output, it is possible to control
479*57b5a4a6SAndroid Build Coastguard Workeraddition of the class discriminator with the [JsonBuilder.classDiscriminatorMode] property.
480*57b5a4a6SAndroid Build Coastguard Worker
481*57b5a4a6SAndroid Build Coastguard WorkerFor example, [ClassDiscriminatorMode.NONE] does not add class discriminator at all, in case the receiving party is not interested in Kotlin types:
482*57b5a4a6SAndroid Build Coastguard Worker
483*57b5a4a6SAndroid Build Coastguard Worker```kotlin
484*57b5a4a6SAndroid Build Coastguard Workerval format = Json { classDiscriminatorMode = ClassDiscriminatorMode.NONE }
485*57b5a4a6SAndroid Build Coastguard Worker
486*57b5a4a6SAndroid Build Coastguard Worker@Serializable
487*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
488*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
489*57b5a4a6SAndroid Build Coastguard Worker}
490*57b5a4a6SAndroid Build Coastguard Worker
491*57b5a4a6SAndroid Build Coastguard Worker@Serializable
492*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
493*57b5a4a6SAndroid Build Coastguard Worker
494*57b5a4a6SAndroid Build Coastguard Workerfun main() {
495*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
496*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
497*57b5a4a6SAndroid Build Coastguard Worker}
498*57b5a4a6SAndroid Build Coastguard Worker```
499*57b5a4a6SAndroid Build Coastguard Worker
500*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-12.kt).
501*57b5a4a6SAndroid Build Coastguard Worker
502*57b5a4a6SAndroid Build Coastguard WorkerNote that it would be impossible to deserialize this output back with kotlinx.serialization.
503*57b5a4a6SAndroid Build Coastguard Worker
504*57b5a4a6SAndroid Build Coastguard Worker```text
505*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.coroutines","owner":"kotlin"}
506*57b5a4a6SAndroid Build Coastguard Worker```
507*57b5a4a6SAndroid Build Coastguard Worker
508*57b5a4a6SAndroid Build Coastguard WorkerTwo other available values are [ClassDiscriminatorMode.POLYMORPHIC] (default behavior) and [ClassDiscriminatorMode.ALL_JSON_OBJECTS] (adds discriminator whenever possible).
509*57b5a4a6SAndroid Build Coastguard WorkerConsult their documentation for details.
510*57b5a4a6SAndroid Build Coastguard Worker
511*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
512*57b5a4a6SAndroid Build Coastguard Worker
513*57b5a4a6SAndroid Build Coastguard Worker### Decoding enums in a case-insensitive manner
514*57b5a4a6SAndroid Build Coastguard Worker
515*57b5a4a6SAndroid Build Coastguard Worker[Kotlin's naming policy recommends](https://kotlinlang.org/docs/coding-conventions.html#property-names) naming enum values
516*57b5a4a6SAndroid Build Coastguard Workerusing either uppercase underscore-separated names or upper camel case names.
517*57b5a4a6SAndroid Build Coastguard Worker[Json] uses exact Kotlin enum values names for decoding by default.
518*57b5a4a6SAndroid Build Coastguard WorkerHowever, sometimes third-party JSONs have such values named in lowercase or some mixed case.
519*57b5a4a6SAndroid Build Coastguard WorkerIn this case, it is possible to decode enum values in a case-insensitive manner using [JsonBuilder.decodeEnumsCaseInsensitive] property:
520*57b5a4a6SAndroid Build Coastguard Worker
521*57b5a4a6SAndroid Build Coastguard Worker```kotlin
522*57b5a4a6SAndroid Build Coastguard Workerval format = Json { decodeEnumsCaseInsensitive = true }
523*57b5a4a6SAndroid Build Coastguard Worker
524*57b5a4a6SAndroid Build Coastguard Workerenum class Cases { VALUE_A, @JsonNames("Alternative") VALUE_B }
525*57b5a4a6SAndroid Build Coastguard Worker
526*57b5a4a6SAndroid Build Coastguard Worker@Serializable
527*57b5a4a6SAndroid Build Coastguard Workerdata class CasesList(val cases: List<Cases>)
528*57b5a4a6SAndroid Build Coastguard Worker
529*57b5a4a6SAndroid Build Coastguard Workerfun main() {
530*57b5a4a6SAndroid Build Coastguard Worker  println(format.decodeFromString<CasesList>("""{"cases":["value_A", "alternative"]}"""))
531*57b5a4a6SAndroid Build Coastguard Worker}
532*57b5a4a6SAndroid Build Coastguard Worker```
533*57b5a4a6SAndroid Build Coastguard Worker
534*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-13.kt).
535*57b5a4a6SAndroid Build Coastguard Worker
536*57b5a4a6SAndroid Build Coastguard WorkerIt affects serial names as well as alternative names specified with [JsonNames] annotation, so both values are successfully decoded:
537*57b5a4a6SAndroid Build Coastguard Worker
538*57b5a4a6SAndroid Build Coastguard Worker```text
539*57b5a4a6SAndroid Build Coastguard WorkerCasesList(cases=[VALUE_A, VALUE_B])
540*57b5a4a6SAndroid Build Coastguard Worker```
541*57b5a4a6SAndroid Build Coastguard Worker
542*57b5a4a6SAndroid Build Coastguard WorkerThis property does not affect encoding in any way.
543*57b5a4a6SAndroid Build Coastguard Worker
544*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
545*57b5a4a6SAndroid Build Coastguard Worker
546*57b5a4a6SAndroid Build Coastguard Worker### Global naming strategy
547*57b5a4a6SAndroid Build Coastguard Worker
548*57b5a4a6SAndroid Build Coastguard WorkerIf properties' names in Json input are different from Kotlin ones, it is recommended to specify the name
549*57b5a4a6SAndroid Build Coastguard Workerfor each property explicitly using [`@SerialName` annotation](basic-serialization.md#serial-field-names).
550*57b5a4a6SAndroid Build Coastguard WorkerHowever, there are certain situations where transformation should be applied to every serial name — such as migration
551*57b5a4a6SAndroid Build Coastguard Workerfrom other frameworks or legacy codebase. For that cases, it is possible to specify a [namingStrategy][JsonBuilder.namingStrategy]
552*57b5a4a6SAndroid Build Coastguard Workerfor a [Json] instance. `kotlinx.serialization` provides one strategy implementation out of the box, the [JsonNamingStrategy.SnakeCase](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-naming-strategy/-builtins/-snake-case.html):
553*57b5a4a6SAndroid Build Coastguard Worker
554*57b5a4a6SAndroid Build Coastguard Worker```kotlin
555*57b5a4a6SAndroid Build Coastguard Worker@Serializable
556*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val projectName: String, val projectOwner: String)
557*57b5a4a6SAndroid Build Coastguard Worker
558*57b5a4a6SAndroid Build Coastguard Workerval format = Json { namingStrategy = JsonNamingStrategy.SnakeCase }
559*57b5a4a6SAndroid Build Coastguard Worker
560*57b5a4a6SAndroid Build Coastguard Workerfun main() {
561*57b5a4a6SAndroid Build Coastguard Worker    val project = format.decodeFromString<Project>("""{"project_name":"kotlinx.coroutines", "project_owner":"Kotlin"}""")
562*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(project.copy(projectName = "kotlinx.serialization")))
563*57b5a4a6SAndroid Build Coastguard Worker}
564*57b5a4a6SAndroid Build Coastguard Worker```
565*57b5a4a6SAndroid Build Coastguard Worker
566*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-14.kt).
567*57b5a4a6SAndroid Build Coastguard Worker
568*57b5a4a6SAndroid Build Coastguard WorkerAs you can see, both serialization and deserialization work as if all serial names are transformed from camel case to snake case:
569*57b5a4a6SAndroid Build Coastguard Worker
570*57b5a4a6SAndroid Build Coastguard Worker```text
571*57b5a4a6SAndroid Build Coastguard Worker{"project_name":"kotlinx.serialization","project_owner":"Kotlin"}
572*57b5a4a6SAndroid Build Coastguard Worker```
573*57b5a4a6SAndroid Build Coastguard Worker
574*57b5a4a6SAndroid Build Coastguard WorkerThere are some caveats one should remember while dealing with a [JsonNamingStrategy]:
575*57b5a4a6SAndroid Build Coastguard Worker
576*57b5a4a6SAndroid Build Coastguard Worker* Due to the nature of the `kotlinx.serialization` framework, naming strategy transformation is applied to all properties regardless
577*57b5a4a6SAndroid Build Coastguard Workerof whether their serial name was taken from the property name or provided by [SerialName] annotation.
578*57b5a4a6SAndroid Build Coastguard WorkerEffectively, it means one cannot avoid transformation by explicitly specifying the serial name. To be able to deserialize
579*57b5a4a6SAndroid Build Coastguard Workernon-transformed names, [JsonNames] annotation can be used instead.
580*57b5a4a6SAndroid Build Coastguard Worker
581*57b5a4a6SAndroid Build Coastguard Worker* Collision of the transformed name with any other (transformed) properties serial names or any alternative names
582*57b5a4a6SAndroid Build Coastguard Workerspecified with [JsonNames] will lead to a deserialization exception.
583*57b5a4a6SAndroid Build Coastguard Worker
584*57b5a4a6SAndroid Build Coastguard Worker* Global naming strategies are very implicit: by looking only at the definition of the class,
585*57b5a4a6SAndroid Build Coastguard Workerit is impossible to determine which names it will have in the serialized form.
586*57b5a4a6SAndroid Build Coastguard WorkerAs a consequence, naming strategies are not friendly to actions like Find Usages/Rename in IDE, full-text search by grep, etc.
587*57b5a4a6SAndroid Build Coastguard WorkerFor them, the original name and the transformed are two different things;
588*57b5a4a6SAndroid Build Coastguard Workerchanging one without the other may introduce bugs in many unexpected ways and lead to greater maintenance efforts for code with global naming strategies.
589*57b5a4a6SAndroid Build Coastguard Worker
590*57b5a4a6SAndroid Build Coastguard WorkerTherefore, one should carefully weigh the pros and cons before considering adding global naming strategies to an application.
591*57b5a4a6SAndroid Build Coastguard Worker
592*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
593*57b5a4a6SAndroid Build Coastguard Worker
594*57b5a4a6SAndroid Build Coastguard Worker## Json elements
595*57b5a4a6SAndroid Build Coastguard Worker
596*57b5a4a6SAndroid Build Coastguard WorkerAside from direct conversions between strings and JSON objects, Kotlin serialization offers APIs that allow
597*57b5a4a6SAndroid Build Coastguard Workerother ways of working with JSON in the code. For example, you might need to tweak the data before it can parse
598*57b5a4a6SAndroid Build Coastguard Workeror otherwise work with such an unstructured data that it does not readily fit into the typesafe world of Kotlin
599*57b5a4a6SAndroid Build Coastguard Workerserialization.
600*57b5a4a6SAndroid Build Coastguard Worker
601*57b5a4a6SAndroid Build Coastguard WorkerThe main concept in this part of the library is [JsonElement]. Read on to learn what you can do with it.
602*57b5a4a6SAndroid Build Coastguard Worker
603*57b5a4a6SAndroid Build Coastguard Worker### Parsing to Json element
604*57b5a4a6SAndroid Build Coastguard Worker
605*57b5a4a6SAndroid Build Coastguard WorkerA string can be _parsed_ into an instance of [JsonElement] with the [Json.parseToJsonElement] function.
606*57b5a4a6SAndroid Build Coastguard WorkerIt is called neither decoding nor deserialization because none of that happens in the process.
607*57b5a4a6SAndroid Build Coastguard WorkerIt just parses a JSON and forms an object representing it:
608*57b5a4a6SAndroid Build Coastguard Worker
609*57b5a4a6SAndroid Build Coastguard Worker```kotlin
610*57b5a4a6SAndroid Build Coastguard Workerfun main() {
611*57b5a4a6SAndroid Build Coastguard Worker    val element = Json.parseToJsonElement("""
612*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","language":"Kotlin"}
613*57b5a4a6SAndroid Build Coastguard Worker    """)
614*57b5a4a6SAndroid Build Coastguard Worker    println(element)
615*57b5a4a6SAndroid Build Coastguard Worker}
616*57b5a4a6SAndroid Build Coastguard Worker```
617*57b5a4a6SAndroid Build Coastguard Worker
618*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-15.kt).
619*57b5a4a6SAndroid Build Coastguard Worker
620*57b5a4a6SAndroid Build Coastguard WorkerA `JsonElement` prints itself as a valid JSON:
621*57b5a4a6SAndroid Build Coastguard Worker
622*57b5a4a6SAndroid Build Coastguard Worker```text
623*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","language":"Kotlin"}
624*57b5a4a6SAndroid Build Coastguard Worker```
625*57b5a4a6SAndroid Build Coastguard Worker
626*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
627*57b5a4a6SAndroid Build Coastguard Worker
628*57b5a4a6SAndroid Build Coastguard Worker### Types of Json elements
629*57b5a4a6SAndroid Build Coastguard Worker
630*57b5a4a6SAndroid Build Coastguard WorkerA [JsonElement] class has three direct subtypes, closely following JSON grammar:
631*57b5a4a6SAndroid Build Coastguard Worker
632*57b5a4a6SAndroid Build Coastguard Worker* [JsonPrimitive] represents primitive JSON elements, such as string, number, boolean, and null.
633*57b5a4a6SAndroid Build Coastguard Worker  Each primitive has a simple string [content][JsonPrimitive.content]. There is also a
634*57b5a4a6SAndroid Build Coastguard Worker  [JsonPrimitive()] constructor function overloaded to accept various primitive Kotlin types and
635*57b5a4a6SAndroid Build Coastguard Worker  to convert them to `JsonPrimitive`.
636*57b5a4a6SAndroid Build Coastguard Worker
637*57b5a4a6SAndroid Build Coastguard Worker* [JsonArray] represents a JSON `[...]` array. It is a Kotlin [List] of `JsonElement` items.
638*57b5a4a6SAndroid Build Coastguard Worker
639*57b5a4a6SAndroid Build Coastguard Worker* [JsonObject] represents a JSON `{...}` object. It is a Kotlin [Map] from `String` keys to `JsonElement` values.
640*57b5a4a6SAndroid Build Coastguard Worker
641*57b5a4a6SAndroid Build Coastguard WorkerThe `JsonElement` class has extensions that cast it to its corresponding subtypes:
642*57b5a4a6SAndroid Build Coastguard Worker[jsonPrimitive][_jsonPrimitive], [jsonArray][_jsonArray], [jsonObject][_jsonObject]. The `JsonPrimitive` class,
643*57b5a4a6SAndroid Build Coastguard Workerin turn, provides converters to Kotlin primitive types: [int], [intOrNull], [long], [longOrNull],
644*57b5a4a6SAndroid Build Coastguard Workerand similar ones for other types. This is how you can use them for processing JSON whose structure you know:
645*57b5a4a6SAndroid Build Coastguard Worker
646*57b5a4a6SAndroid Build Coastguard Worker```kotlin
647*57b5a4a6SAndroid Build Coastguard Workerfun main() {
648*57b5a4a6SAndroid Build Coastguard Worker    val element = Json.parseToJsonElement("""
649*57b5a4a6SAndroid Build Coastguard Worker        {
650*57b5a4a6SAndroid Build Coastguard Worker            "name": "kotlinx.serialization",
651*57b5a4a6SAndroid Build Coastguard Worker            "forks": [{"votes": 42}, {"votes": 9000}, {}]
652*57b5a4a6SAndroid Build Coastguard Worker        }
653*57b5a4a6SAndroid Build Coastguard Worker    """)
654*57b5a4a6SAndroid Build Coastguard Worker    val sum = element
655*57b5a4a6SAndroid Build Coastguard Worker        .jsonObject["forks"]!!
656*57b5a4a6SAndroid Build Coastguard Worker        .jsonArray.sumOf { it.jsonObject["votes"]?.jsonPrimitive?.int ?: 0 }
657*57b5a4a6SAndroid Build Coastguard Worker    println(sum)
658*57b5a4a6SAndroid Build Coastguard Worker}
659*57b5a4a6SAndroid Build Coastguard Worker```
660*57b5a4a6SAndroid Build Coastguard Worker
661*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-16.kt).
662*57b5a4a6SAndroid Build Coastguard Worker
663*57b5a4a6SAndroid Build Coastguard WorkerThe above example sums `votes` in all objects in the `forks` array, ignoring the objects that have no `votes`:
664*57b5a4a6SAndroid Build Coastguard Worker
665*57b5a4a6SAndroid Build Coastguard Worker```text
666*57b5a4a6SAndroid Build Coastguard Worker9042
667*57b5a4a6SAndroid Build Coastguard Worker```
668*57b5a4a6SAndroid Build Coastguard Worker
669*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
670*57b5a4a6SAndroid Build Coastguard Worker
671*57b5a4a6SAndroid Build Coastguard WorkerNote that the execution will fail if the structure of the data is otherwise different.
672*57b5a4a6SAndroid Build Coastguard Worker
673*57b5a4a6SAndroid Build Coastguard Worker### Json element builders
674*57b5a4a6SAndroid Build Coastguard Worker
675*57b5a4a6SAndroid Build Coastguard WorkerYou can construct instances of specific [JsonElement] subtypes using the respective builder functions
676*57b5a4a6SAndroid Build Coastguard Worker[buildJsonArray] and [buildJsonObject]. They provide a DSL to define the resulting JSON structure. It
677*57b5a4a6SAndroid Build Coastguard Workeris similar to Kotlin standard library collection builders, but with a JSON-specific convenience
678*57b5a4a6SAndroid Build Coastguard Workerof more type-specific overloads and inner builder functions. The following example shows
679*57b5a4a6SAndroid Build Coastguard Workerall the key features:
680*57b5a4a6SAndroid Build Coastguard Worker
681*57b5a4a6SAndroid Build Coastguard Worker```kotlin
682*57b5a4a6SAndroid Build Coastguard Workerfun main() {
683*57b5a4a6SAndroid Build Coastguard Worker    val element = buildJsonObject {
684*57b5a4a6SAndroid Build Coastguard Worker        put("name", "kotlinx.serialization")
685*57b5a4a6SAndroid Build Coastguard Worker        putJsonObject("owner") {
686*57b5a4a6SAndroid Build Coastguard Worker            put("name", "kotlin")
687*57b5a4a6SAndroid Build Coastguard Worker        }
688*57b5a4a6SAndroid Build Coastguard Worker        putJsonArray("forks") {
689*57b5a4a6SAndroid Build Coastguard Worker            addJsonObject {
690*57b5a4a6SAndroid Build Coastguard Worker                put("votes", 42)
691*57b5a4a6SAndroid Build Coastguard Worker            }
692*57b5a4a6SAndroid Build Coastguard Worker            addJsonObject {
693*57b5a4a6SAndroid Build Coastguard Worker                put("votes", 9000)
694*57b5a4a6SAndroid Build Coastguard Worker            }
695*57b5a4a6SAndroid Build Coastguard Worker        }
696*57b5a4a6SAndroid Build Coastguard Worker    }
697*57b5a4a6SAndroid Build Coastguard Worker    println(element)
698*57b5a4a6SAndroid Build Coastguard Worker}
699*57b5a4a6SAndroid Build Coastguard Worker```
700*57b5a4a6SAndroid Build Coastguard Worker
701*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-17.kt).
702*57b5a4a6SAndroid Build Coastguard Worker
703*57b5a4a6SAndroid Build Coastguard WorkerAs a result, you get a proper JSON string:
704*57b5a4a6SAndroid Build Coastguard Worker
705*57b5a4a6SAndroid Build Coastguard Worker```text
706*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","owner":{"name":"kotlin"},"forks":[{"votes":42},{"votes":9000}]}
707*57b5a4a6SAndroid Build Coastguard Worker```
708*57b5a4a6SAndroid Build Coastguard Worker
709*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
710*57b5a4a6SAndroid Build Coastguard Worker
711*57b5a4a6SAndroid Build Coastguard Worker### Decoding Json elements
712*57b5a4a6SAndroid Build Coastguard Worker
713*57b5a4a6SAndroid Build Coastguard WorkerAn instance of the [JsonElement] class can be decoded into a serializable object using
714*57b5a4a6SAndroid Build Coastguard Workerthe [Json.decodeFromJsonElement] function:
715*57b5a4a6SAndroid Build Coastguard Worker
716*57b5a4a6SAndroid Build Coastguard Worker```kotlin
717*57b5a4a6SAndroid Build Coastguard Worker@Serializable
718*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String, val language: String)
719*57b5a4a6SAndroid Build Coastguard Worker
720*57b5a4a6SAndroid Build Coastguard Workerfun main() {
721*57b5a4a6SAndroid Build Coastguard Worker    val element = buildJsonObject {
722*57b5a4a6SAndroid Build Coastguard Worker        put("name", "kotlinx.serialization")
723*57b5a4a6SAndroid Build Coastguard Worker        put("language", "Kotlin")
724*57b5a4a6SAndroid Build Coastguard Worker    }
725*57b5a4a6SAndroid Build Coastguard Worker    val data = Json.decodeFromJsonElement<Project>(element)
726*57b5a4a6SAndroid Build Coastguard Worker    println(data)
727*57b5a4a6SAndroid Build Coastguard Worker}
728*57b5a4a6SAndroid Build Coastguard Worker```
729*57b5a4a6SAndroid Build Coastguard Worker
730*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-18.kt).
731*57b5a4a6SAndroid Build Coastguard Worker
732*57b5a4a6SAndroid Build Coastguard WorkerThe result is exactly what you would expect:
733*57b5a4a6SAndroid Build Coastguard Worker
734*57b5a4a6SAndroid Build Coastguard Worker```text
735*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, language=Kotlin)
736*57b5a4a6SAndroid Build Coastguard Worker```
737*57b5a4a6SAndroid Build Coastguard Worker
738*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
739*57b5a4a6SAndroid Build Coastguard Worker
740*57b5a4a6SAndroid Build Coastguard Worker### Encoding literal Json content (experimental)
741*57b5a4a6SAndroid Build Coastguard Worker
742*57b5a4a6SAndroid Build Coastguard Worker> This functionality is experimental and requires opting-in to [the experimental Kotlinx Serialization API](compatibility.md#experimental-api).
743*57b5a4a6SAndroid Build Coastguard Worker
744*57b5a4a6SAndroid Build Coastguard WorkerIn some cases it might be necessary to encode an arbitrary unquoted value.
745*57b5a4a6SAndroid Build Coastguard WorkerThis can be achieved with [JsonUnquotedLiteral].
746*57b5a4a6SAndroid Build Coastguard Worker
747*57b5a4a6SAndroid Build Coastguard Worker#### Serializing large decimal numbers
748*57b5a4a6SAndroid Build Coastguard Worker
749*57b5a4a6SAndroid Build Coastguard WorkerThe JSON specification does not restrict the size or precision of numbers, however it is not possible to serialize
750*57b5a4a6SAndroid Build Coastguard Workernumbers of arbitrary size or precision using [JsonPrimitive()].
751*57b5a4a6SAndroid Build Coastguard Worker
752*57b5a4a6SAndroid Build Coastguard WorkerIf [Double] is used, then the numbers are limited in precision, meaning that large numbers are truncated.
753*57b5a4a6SAndroid Build Coastguard WorkerWhen using Kotlin/JVM [BigDecimal] can be used instead, but [JsonPrimitive()] will encode the value as a string, not a
754*57b5a4a6SAndroid Build Coastguard Workernumber.
755*57b5a4a6SAndroid Build Coastguard Worker
756*57b5a4a6SAndroid Build Coastguard Worker```kotlin
757*57b5a4a6SAndroid Build Coastguard Workerimport java.math.BigDecimal
758*57b5a4a6SAndroid Build Coastguard Worker
759*57b5a4a6SAndroid Build Coastguard Workerval format = Json { prettyPrint = true }
760*57b5a4a6SAndroid Build Coastguard Worker
761*57b5a4a6SAndroid Build Coastguard Workerfun main() {
762*57b5a4a6SAndroid Build Coastguard Worker    val pi = BigDecimal("3.141592653589793238462643383279")
763*57b5a4a6SAndroid Build Coastguard Worker
764*57b5a4a6SAndroid Build Coastguard Worker    val piJsonDouble = JsonPrimitive(pi.toDouble())
765*57b5a4a6SAndroid Build Coastguard Worker    val piJsonString = JsonPrimitive(pi.toString())
766*57b5a4a6SAndroid Build Coastguard Worker
767*57b5a4a6SAndroid Build Coastguard Worker    val piObject = buildJsonObject {
768*57b5a4a6SAndroid Build Coastguard Worker        put("pi_double", piJsonDouble)
769*57b5a4a6SAndroid Build Coastguard Worker        put("pi_string", piJsonString)
770*57b5a4a6SAndroid Build Coastguard Worker    }
771*57b5a4a6SAndroid Build Coastguard Worker
772*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(piObject))
773*57b5a4a6SAndroid Build Coastguard Worker}
774*57b5a4a6SAndroid Build Coastguard Worker```
775*57b5a4a6SAndroid Build Coastguard Worker
776*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-19.kt).
777*57b5a4a6SAndroid Build Coastguard Worker
778*57b5a4a6SAndroid Build Coastguard WorkerEven though `pi` was defined as a number with 30 decimal places, the resulting JSON does not reflect this.
779*57b5a4a6SAndroid Build Coastguard WorkerThe [Double] value is truncated to 15 decimal places, and the String is wrapped in quotes - which is not a JSON number.
780*57b5a4a6SAndroid Build Coastguard Worker
781*57b5a4a6SAndroid Build Coastguard Worker```text
782*57b5a4a6SAndroid Build Coastguard Worker{
783*57b5a4a6SAndroid Build Coastguard Worker    "pi_double": 3.141592653589793,
784*57b5a4a6SAndroid Build Coastguard Worker    "pi_string": "3.141592653589793238462643383279"
785*57b5a4a6SAndroid Build Coastguard Worker}
786*57b5a4a6SAndroid Build Coastguard Worker```
787*57b5a4a6SAndroid Build Coastguard Worker
788*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
789*57b5a4a6SAndroid Build Coastguard Worker
790*57b5a4a6SAndroid Build Coastguard WorkerTo avoid precision loss, the string value of `pi` can be encoded using [JsonUnquotedLiteral].
791*57b5a4a6SAndroid Build Coastguard Worker
792*57b5a4a6SAndroid Build Coastguard Worker```kotlin
793*57b5a4a6SAndroid Build Coastguard Workerimport java.math.BigDecimal
794*57b5a4a6SAndroid Build Coastguard Worker
795*57b5a4a6SAndroid Build Coastguard Workerval format = Json { prettyPrint = true }
796*57b5a4a6SAndroid Build Coastguard Worker
797*57b5a4a6SAndroid Build Coastguard Workerfun main() {
798*57b5a4a6SAndroid Build Coastguard Worker    val pi = BigDecimal("3.141592653589793238462643383279")
799*57b5a4a6SAndroid Build Coastguard Worker
800*57b5a4a6SAndroid Build Coastguard Worker    // use JsonUnquotedLiteral to encode raw JSON content
801*57b5a4a6SAndroid Build Coastguard Worker    val piJsonLiteral = JsonUnquotedLiteral(pi.toString())
802*57b5a4a6SAndroid Build Coastguard Worker
803*57b5a4a6SAndroid Build Coastguard Worker    val piJsonDouble = JsonPrimitive(pi.toDouble())
804*57b5a4a6SAndroid Build Coastguard Worker    val piJsonString = JsonPrimitive(pi.toString())
805*57b5a4a6SAndroid Build Coastguard Worker
806*57b5a4a6SAndroid Build Coastguard Worker    val piObject = buildJsonObject {
807*57b5a4a6SAndroid Build Coastguard Worker        put("pi_literal", piJsonLiteral)
808*57b5a4a6SAndroid Build Coastguard Worker        put("pi_double", piJsonDouble)
809*57b5a4a6SAndroid Build Coastguard Worker        put("pi_string", piJsonString)
810*57b5a4a6SAndroid Build Coastguard Worker    }
811*57b5a4a6SAndroid Build Coastguard Worker
812*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(piObject))
813*57b5a4a6SAndroid Build Coastguard Worker}
814*57b5a4a6SAndroid Build Coastguard Worker```
815*57b5a4a6SAndroid Build Coastguard Worker
816*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-20.kt).
817*57b5a4a6SAndroid Build Coastguard Worker
818*57b5a4a6SAndroid Build Coastguard Worker`pi_literal` now accurately matches the value defined.
819*57b5a4a6SAndroid Build Coastguard Worker
820*57b5a4a6SAndroid Build Coastguard Worker```text
821*57b5a4a6SAndroid Build Coastguard Worker{
822*57b5a4a6SAndroid Build Coastguard Worker    "pi_literal": 3.141592653589793238462643383279,
823*57b5a4a6SAndroid Build Coastguard Worker    "pi_double": 3.141592653589793,
824*57b5a4a6SAndroid Build Coastguard Worker    "pi_string": "3.141592653589793238462643383279"
825*57b5a4a6SAndroid Build Coastguard Worker}
826*57b5a4a6SAndroid Build Coastguard Worker```
827*57b5a4a6SAndroid Build Coastguard Worker
828*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
829*57b5a4a6SAndroid Build Coastguard Worker
830*57b5a4a6SAndroid Build Coastguard WorkerTo decode `pi` back to a [BigDecimal], the string content of the [JsonPrimitive] can be used.
831*57b5a4a6SAndroid Build Coastguard Worker
832*57b5a4a6SAndroid Build Coastguard Worker(This demonstration uses a [JsonPrimitive] for simplicity. For a more re-usable method of handling serialization, see
833*57b5a4a6SAndroid Build Coastguard Worker[Json Transformations](#json-transformations) below.)
834*57b5a4a6SAndroid Build Coastguard Worker
835*57b5a4a6SAndroid Build Coastguard Worker
836*57b5a4a6SAndroid Build Coastguard Worker```kotlin
837*57b5a4a6SAndroid Build Coastguard Workerimport java.math.BigDecimal
838*57b5a4a6SAndroid Build Coastguard Worker
839*57b5a4a6SAndroid Build Coastguard Workerfun main() {
840*57b5a4a6SAndroid Build Coastguard Worker    val piObjectJson = """
841*57b5a4a6SAndroid Build Coastguard Worker          {
842*57b5a4a6SAndroid Build Coastguard Worker              "pi_literal": 3.141592653589793238462643383279
843*57b5a4a6SAndroid Build Coastguard Worker          }
844*57b5a4a6SAndroid Build Coastguard Worker      """.trimIndent()
845*57b5a4a6SAndroid Build Coastguard Worker
846*57b5a4a6SAndroid Build Coastguard Worker    val piObject: JsonObject = Json.decodeFromString(piObjectJson)
847*57b5a4a6SAndroid Build Coastguard Worker
848*57b5a4a6SAndroid Build Coastguard Worker    val piJsonLiteral = piObject["pi_literal"]!!.jsonPrimitive.content
849*57b5a4a6SAndroid Build Coastguard Worker
850*57b5a4a6SAndroid Build Coastguard Worker    val pi = BigDecimal(piJsonLiteral)
851*57b5a4a6SAndroid Build Coastguard Worker
852*57b5a4a6SAndroid Build Coastguard Worker    println(pi)
853*57b5a4a6SAndroid Build Coastguard Worker}
854*57b5a4a6SAndroid Build Coastguard Worker```
855*57b5a4a6SAndroid Build Coastguard Worker
856*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-21.kt).
857*57b5a4a6SAndroid Build Coastguard Worker
858*57b5a4a6SAndroid Build Coastguard WorkerThe exact value of `pi` is decoded, with all 30 decimal places of precision that were in the source JSON.
859*57b5a4a6SAndroid Build Coastguard Worker
860*57b5a4a6SAndroid Build Coastguard Worker```text
861*57b5a4a6SAndroid Build Coastguard Worker3.141592653589793238462643383279
862*57b5a4a6SAndroid Build Coastguard Worker```
863*57b5a4a6SAndroid Build Coastguard Worker
864*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
865*57b5a4a6SAndroid Build Coastguard Worker
866*57b5a4a6SAndroid Build Coastguard Worker#### Using `JsonUnquotedLiteral` to create a literal unquoted value of `null` is forbidden
867*57b5a4a6SAndroid Build Coastguard Worker
868*57b5a4a6SAndroid Build Coastguard WorkerTo avoid creating an inconsistent state, encoding a String equal to `"null"` is forbidden.
869*57b5a4a6SAndroid Build Coastguard WorkerUse [JsonNull] or [JsonPrimitive] instead.
870*57b5a4a6SAndroid Build Coastguard Worker
871*57b5a4a6SAndroid Build Coastguard Worker```kotlin
872*57b5a4a6SAndroid Build Coastguard Workerfun main() {
873*57b5a4a6SAndroid Build Coastguard Worker    // caution: creating null with JsonUnquotedLiteral will cause an exception!
874*57b5a4a6SAndroid Build Coastguard Worker    JsonUnquotedLiteral("null")
875*57b5a4a6SAndroid Build Coastguard Worker}
876*57b5a4a6SAndroid Build Coastguard Worker```
877*57b5a4a6SAndroid Build Coastguard Worker
878*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-22.kt).
879*57b5a4a6SAndroid Build Coastguard Worker
880*57b5a4a6SAndroid Build Coastguard Worker```text
881*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.json.internal.JsonEncodingException: Creating a literal unquoted value of 'null' is forbidden. If you want to create JSON null literal, use JsonNull object, otherwise, use JsonPrimitive
882*57b5a4a6SAndroid Build Coastguard Worker```
883*57b5a4a6SAndroid Build Coastguard Worker
884*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
885*57b5a4a6SAndroid Build Coastguard Worker
886*57b5a4a6SAndroid Build Coastguard Worker
887*57b5a4a6SAndroid Build Coastguard Worker## Json transformations
888*57b5a4a6SAndroid Build Coastguard Worker
889*57b5a4a6SAndroid Build Coastguard WorkerTo affect the shape and contents of JSON output after serialization, or adapt input to deserialization,
890*57b5a4a6SAndroid Build Coastguard Workerit is possible to write a [custom serializer](serializers.md). However, it may be inconvenient to
891*57b5a4a6SAndroid Build Coastguard Workercarefully follow [Encoder] and [Decoder] calling conventions, especially for relatively small and easy tasks.
892*57b5a4a6SAndroid Build Coastguard WorkerFor that purpose, Kotlin serialization provides an API that can reduce the burden of implementing a custom
893*57b5a4a6SAndroid Build Coastguard Workerserializer to a problem of manipulating a Json elements tree.
894*57b5a4a6SAndroid Build Coastguard Worker
895*57b5a4a6SAndroid Build Coastguard WorkerWe recommend that you get familiar with the [Serializers](serializers.md) chapter: among other things, it
896*57b5a4a6SAndroid Build Coastguard Workerexplains how custom serializers are bound to classes.
897*57b5a4a6SAndroid Build Coastguard Worker
898*57b5a4a6SAndroid Build Coastguard WorkerTransformation capabilities are provided by the abstract [JsonTransformingSerializer] class which implements [KSerializer].
899*57b5a4a6SAndroid Build Coastguard WorkerInstead of direct interaction with `Encoder` or `Decoder`, this class asks you to supply transformations for JSON tree
900*57b5a4a6SAndroid Build Coastguard Workerrepresented by the [JsonElement] class using the`transformSerialize` and
901*57b5a4a6SAndroid Build Coastguard Worker`transformDeserialize` methods. Let's take a look at the examples.
902*57b5a4a6SAndroid Build Coastguard Worker
903*57b5a4a6SAndroid Build Coastguard Worker### Array wrapping
904*57b5a4a6SAndroid Build Coastguard Worker
905*57b5a4a6SAndroid Build Coastguard WorkerThe first example is an implementation of JSON array wrapping for lists.
906*57b5a4a6SAndroid Build Coastguard Worker
907*57b5a4a6SAndroid Build Coastguard WorkerConsider a REST API that returns a JSON array of `User` objects, or a single object (not wrapped into an array) if there
908*57b5a4a6SAndroid Build Coastguard Workeris only one element in the result.
909*57b5a4a6SAndroid Build Coastguard Worker
910*57b5a4a6SAndroid Build Coastguard WorkerIn the data model, use the [`@Serializable`][Serializable] annotation to specify a custom serializer for a
911*57b5a4a6SAndroid Build Coastguard Worker`users: List<User>` property.
912*57b5a4a6SAndroid Build Coastguard Worker
913*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
914*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.builtins.*
915*57b5a4a6SAndroid Build Coastguard Worker-->
916*57b5a4a6SAndroid Build Coastguard Worker
917*57b5a4a6SAndroid Build Coastguard Worker```kotlin
918*57b5a4a6SAndroid Build Coastguard Worker@Serializable
919*57b5a4a6SAndroid Build Coastguard Workerdata class Project(
920*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
921*57b5a4a6SAndroid Build Coastguard Worker    @Serializable(with = UserListSerializer::class)
922*57b5a4a6SAndroid Build Coastguard Worker    val users: List<User>
923*57b5a4a6SAndroid Build Coastguard Worker)
924*57b5a4a6SAndroid Build Coastguard Worker
925*57b5a4a6SAndroid Build Coastguard Worker@Serializable
926*57b5a4a6SAndroid Build Coastguard Workerdata class User(val name: String)
927*57b5a4a6SAndroid Build Coastguard Worker```
928*57b5a4a6SAndroid Build Coastguard Worker
929*57b5a4a6SAndroid Build Coastguard WorkerSince this example covers only the deserialization case, you can implement `UserListSerializer` and override only the
930*57b5a4a6SAndroid Build Coastguard Worker`transformDeserialize` function. The `JsonTransformingSerializer` constructor takes an original serializer
931*57b5a4a6SAndroid Build Coastguard Workeras parameter (this approach is shown in the section [Constructing collection serializers](serializers.md#constructing-collection-serializers)):
932*57b5a4a6SAndroid Build Coastguard Worker
933*57b5a4a6SAndroid Build Coastguard Worker```kotlin
934*57b5a4a6SAndroid Build Coastguard Workerobject UserListSerializer : JsonTransformingSerializer<List<User>>(ListSerializer(User.serializer())) {
935*57b5a4a6SAndroid Build Coastguard Worker    // If response is not an array, then it is a single object that should be wrapped into the array
936*57b5a4a6SAndroid Build Coastguard Worker    override fun transformDeserialize(element: JsonElement): JsonElement =
937*57b5a4a6SAndroid Build Coastguard Worker        if (element !is JsonArray) JsonArray(listOf(element)) else element
938*57b5a4a6SAndroid Build Coastguard Worker}
939*57b5a4a6SAndroid Build Coastguard Worker```
940*57b5a4a6SAndroid Build Coastguard Worker
941*57b5a4a6SAndroid Build Coastguard WorkerNow you can test the code with a JSON array or a single JSON object as inputs.
942*57b5a4a6SAndroid Build Coastguard Worker
943*57b5a4a6SAndroid Build Coastguard Worker```kotlin
944*57b5a4a6SAndroid Build Coastguard Workerfun main() {
945*57b5a4a6SAndroid Build Coastguard Worker    println(Json.decodeFromString<Project>("""
946*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","users":{"name":"kotlin"}}
947*57b5a4a6SAndroid Build Coastguard Worker    """))
948*57b5a4a6SAndroid Build Coastguard Worker    println(Json.decodeFromString<Project>("""
949*57b5a4a6SAndroid Build Coastguard Worker        {"name":"kotlinx.serialization","users":[{"name":"kotlin"},{"name":"jetbrains"}]}
950*57b5a4a6SAndroid Build Coastguard Worker    """))
951*57b5a4a6SAndroid Build Coastguard Worker}
952*57b5a4a6SAndroid Build Coastguard Worker```
953*57b5a4a6SAndroid Build Coastguard Worker
954*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-23.kt).
955*57b5a4a6SAndroid Build Coastguard Worker
956*57b5a4a6SAndroid Build Coastguard WorkerThe output shows that both cases are correctly deserialized into a Kotlin [List].
957*57b5a4a6SAndroid Build Coastguard Worker
958*57b5a4a6SAndroid Build Coastguard Worker```text
959*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, users=[User(name=kotlin)])
960*57b5a4a6SAndroid Build Coastguard WorkerProject(name=kotlinx.serialization, users=[User(name=kotlin), User(name=jetbrains)])
961*57b5a4a6SAndroid Build Coastguard Worker```
962*57b5a4a6SAndroid Build Coastguard Worker
963*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
964*57b5a4a6SAndroid Build Coastguard Worker
965*57b5a4a6SAndroid Build Coastguard Worker### Array unwrapping
966*57b5a4a6SAndroid Build Coastguard Worker
967*57b5a4a6SAndroid Build Coastguard WorkerYou can also implement the `transformSerialize` function to unwrap a single-element list into a single JSON object
968*57b5a4a6SAndroid Build Coastguard Workerduring serialization:
969*57b5a4a6SAndroid Build Coastguard Worker
970*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
971*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.builtins.*
972*57b5a4a6SAndroid Build Coastguard Worker
973*57b5a4a6SAndroid Build Coastguard Worker@Serializable
974*57b5a4a6SAndroid Build Coastguard Workerdata class Project(
975*57b5a4a6SAndroid Build Coastguard Worker    val name: String,
976*57b5a4a6SAndroid Build Coastguard Worker    @Serializable(with = UserListSerializer::class)
977*57b5a4a6SAndroid Build Coastguard Worker    val users: List<User>
978*57b5a4a6SAndroid Build Coastguard Worker)
979*57b5a4a6SAndroid Build Coastguard Worker
980*57b5a4a6SAndroid Build Coastguard Worker@Serializable
981*57b5a4a6SAndroid Build Coastguard Workerdata class User(val name: String)
982*57b5a4a6SAndroid Build Coastguard Worker
983*57b5a4a6SAndroid Build Coastguard Workerobject UserListSerializer : JsonTransformingSerializer<List<User>>(ListSerializer(User.serializer())) {
984*57b5a4a6SAndroid Build Coastguard Worker-->
985*57b5a4a6SAndroid Build Coastguard Worker
986*57b5a4a6SAndroid Build Coastguard Worker```kotlin
987*57b5a4a6SAndroid Build Coastguard Worker    override fun transformSerialize(element: JsonElement): JsonElement {
988*57b5a4a6SAndroid Build Coastguard Worker        require(element is JsonArray) // this serializer is used only with lists
989*57b5a4a6SAndroid Build Coastguard Worker        return element.singleOrNull() ?: element
990*57b5a4a6SAndroid Build Coastguard Worker    }
991*57b5a4a6SAndroid Build Coastguard Worker```
992*57b5a4a6SAndroid Build Coastguard Worker
993*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
994*57b5a4a6SAndroid Build Coastguard Worker}
995*57b5a4a6SAndroid Build Coastguard Worker-->
996*57b5a4a6SAndroid Build Coastguard Worker
997*57b5a4a6SAndroid Build Coastguard WorkerNow, if you serialize a single-element list of objects from Kotlin:
998*57b5a4a6SAndroid Build Coastguard Worker
999*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1000*57b5a4a6SAndroid Build Coastguard Workerfun main() {
1001*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", listOf(User("kotlin")))
1002*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
1003*57b5a4a6SAndroid Build Coastguard Worker}
1004*57b5a4a6SAndroid Build Coastguard Worker```
1005*57b5a4a6SAndroid Build Coastguard Worker
1006*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-24.kt).
1007*57b5a4a6SAndroid Build Coastguard Worker
1008*57b5a4a6SAndroid Build Coastguard WorkerYou end up with a single JSON object, not an array with one element:
1009*57b5a4a6SAndroid Build Coastguard Worker
1010*57b5a4a6SAndroid Build Coastguard Worker```text
1011*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","users":{"name":"kotlin"}}
1012*57b5a4a6SAndroid Build Coastguard Worker```
1013*57b5a4a6SAndroid Build Coastguard Worker
1014*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1015*57b5a4a6SAndroid Build Coastguard Worker
1016*57b5a4a6SAndroid Build Coastguard Worker### Manipulating default values
1017*57b5a4a6SAndroid Build Coastguard Worker
1018*57b5a4a6SAndroid Build Coastguard WorkerAnother kind of useful transformation is omitting specific values from the output JSON, for example, if it
1019*57b5a4a6SAndroid Build Coastguard Workeris used as default when missing or for other reasons.
1020*57b5a4a6SAndroid Build Coastguard Worker
1021*57b5a4a6SAndroid Build Coastguard WorkerImagine that you cannot specify a default value for the `language` property in the `Project` data model for some reason,
1022*57b5a4a6SAndroid Build Coastguard Workerbut you need it omitted from the JSON when it is equal to `Kotlin` (we can all agree that Kotlin should be default anyway).
1023*57b5a4a6SAndroid Build Coastguard WorkerYou can fix it by writing the special `ProjectSerializer` based on
1024*57b5a4a6SAndroid Build Coastguard Workerthe [Plugin-generated serializer](serializers.md#plugin-generated-serializer) for the `Project` class.
1025*57b5a4a6SAndroid Build Coastguard Worker
1026*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1027*57b5a4a6SAndroid Build Coastguard Worker@Serializable
1028*57b5a4a6SAndroid Build Coastguard Workerclass Project(val name: String, val language: String)
1029*57b5a4a6SAndroid Build Coastguard Worker
1030*57b5a4a6SAndroid Build Coastguard Workerobject ProjectSerializer : JsonTransformingSerializer<Project>(Project.serializer()) {
1031*57b5a4a6SAndroid Build Coastguard Worker    override fun transformSerialize(element: JsonElement): JsonElement =
1032*57b5a4a6SAndroid Build Coastguard Worker        // Filter out top-level key value pair with the key "language" and the value "Kotlin"
1033*57b5a4a6SAndroid Build Coastguard Worker        JsonObject(element.jsonObject.filterNot {
1034*57b5a4a6SAndroid Build Coastguard Worker            (k, v) -> k == "language" && v.jsonPrimitive.content == "Kotlin"
1035*57b5a4a6SAndroid Build Coastguard Worker        })
1036*57b5a4a6SAndroid Build Coastguard Worker}
1037*57b5a4a6SAndroid Build Coastguard Worker```
1038*57b5a4a6SAndroid Build Coastguard Worker
1039*57b5a4a6SAndroid Build Coastguard WorkerIn the example below, we are serializing the `Project` class at the top-level, so we explicitly
1040*57b5a4a6SAndroid Build Coastguard Workerpass the above `ProjectSerializer` to [Json.encodeToString] function as was shown in
1041*57b5a4a6SAndroid Build Coastguard Workerthe [Passing a serializer manually](serializers.md#passing-a-serializer-manually) section:
1042*57b5a4a6SAndroid Build Coastguard Worker
1043*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1044*57b5a4a6SAndroid Build Coastguard Workerfun main() {
1045*57b5a4a6SAndroid Build Coastguard Worker    val data = Project("kotlinx.serialization", "Kotlin")
1046*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data)) // using plugin-generated serializer
1047*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(ProjectSerializer, data)) // using custom serializer
1048*57b5a4a6SAndroid Build Coastguard Worker}
1049*57b5a4a6SAndroid Build Coastguard Worker```
1050*57b5a4a6SAndroid Build Coastguard Worker
1051*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-25.kt).
1052*57b5a4a6SAndroid Build Coastguard Worker
1053*57b5a4a6SAndroid Build Coastguard WorkerSee the effect of the custom serializer:
1054*57b5a4a6SAndroid Build Coastguard Worker
1055*57b5a4a6SAndroid Build Coastguard Worker```text
1056*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization","language":"Kotlin"}
1057*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.serialization"}
1058*57b5a4a6SAndroid Build Coastguard Worker```
1059*57b5a4a6SAndroid Build Coastguard Worker
1060*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1061*57b5a4a6SAndroid Build Coastguard Worker
1062*57b5a4a6SAndroid Build Coastguard Worker### Content-based polymorphic deserialization
1063*57b5a4a6SAndroid Build Coastguard Worker
1064*57b5a4a6SAndroid Build Coastguard WorkerTypically, [polymorphic serialization](polymorphism.md) requires a dedicated `"type"` key
1065*57b5a4a6SAndroid Build Coastguard Worker(also known as _class discriminator_) in the incoming JSON object to determine the actual serializer
1066*57b5a4a6SAndroid Build Coastguard Workerwhich should be used to deserialize Kotlin class.
1067*57b5a4a6SAndroid Build Coastguard Worker
1068*57b5a4a6SAndroid Build Coastguard WorkerHowever, sometimes the `type` property may not be present in the input. In this case, you need to guess
1069*57b5a4a6SAndroid Build Coastguard Workerthe actual type by the shape of JSON, for example by the presence of a specific key.
1070*57b5a4a6SAndroid Build Coastguard Worker
1071*57b5a4a6SAndroid Build Coastguard Worker[JsonContentPolymorphicSerializer] provides a skeleton implementation for such a strategy.
1072*57b5a4a6SAndroid Build Coastguard WorkerTo use it, override its `selectDeserializer` method.
1073*57b5a4a6SAndroid Build Coastguard WorkerLet's start with the following class hierarchy.
1074*57b5a4a6SAndroid Build Coastguard Worker
1075*57b5a4a6SAndroid Build Coastguard Worker> Note that is does not have to be `sealed` as recommended in the [Sealed classes](polymorphism.md#sealed-classes) section,
1076*57b5a4a6SAndroid Build Coastguard Worker> because we are not going to take advantage of the plugin-generated code that automatically selects the
1077*57b5a4a6SAndroid Build Coastguard Worker> appropriate subclass, but are going to implement this code manually.
1078*57b5a4a6SAndroid Build Coastguard Worker
1079*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
1080*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.builtins.*
1081*57b5a4a6SAndroid Build Coastguard Worker-->
1082*57b5a4a6SAndroid Build Coastguard Worker
1083*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1084*57b5a4a6SAndroid Build Coastguard Worker@Serializable
1085*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
1086*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
1087*57b5a4a6SAndroid Build Coastguard Worker}
1088*57b5a4a6SAndroid Build Coastguard Worker
1089*57b5a4a6SAndroid Build Coastguard Worker@Serializable
1090*57b5a4a6SAndroid Build Coastguard Workerdata class BasicProject(override val name: String): Project()
1091*57b5a4a6SAndroid Build Coastguard Worker
1092*57b5a4a6SAndroid Build Coastguard Worker
1093*57b5a4a6SAndroid Build Coastguard Worker@Serializable
1094*57b5a4a6SAndroid Build Coastguard Workerdata class OwnedProject(override val name: String, val owner: String) : Project()
1095*57b5a4a6SAndroid Build Coastguard Worker```
1096*57b5a4a6SAndroid Build Coastguard Worker
1097*57b5a4a6SAndroid Build Coastguard WorkerYou can distinguish the `BasicProject` and `OwnedProject` subclasses by the presence of
1098*57b5a4a6SAndroid Build Coastguard Workerthe `owner` key in the JSON object.
1099*57b5a4a6SAndroid Build Coastguard Worker
1100*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1101*57b5a4a6SAndroid Build Coastguard Workerobject ProjectSerializer : JsonContentPolymorphicSerializer<Project>(Project::class) {
1102*57b5a4a6SAndroid Build Coastguard Worker    override fun selectDeserializer(element: JsonElement) = when {
1103*57b5a4a6SAndroid Build Coastguard Worker        "owner" in element.jsonObject -> OwnedProject.serializer()
1104*57b5a4a6SAndroid Build Coastguard Worker        else -> BasicProject.serializer()
1105*57b5a4a6SAndroid Build Coastguard Worker    }
1106*57b5a4a6SAndroid Build Coastguard Worker}
1107*57b5a4a6SAndroid Build Coastguard Worker```
1108*57b5a4a6SAndroid Build Coastguard Worker
1109*57b5a4a6SAndroid Build Coastguard WorkerWhen you use this serializer to serialize data, either [registered](polymorphism.md#registered-subclasses) or
1110*57b5a4a6SAndroid Build Coastguard Workerthe default serializer is selected for the actual type at runtime:
1111*57b5a4a6SAndroid Build Coastguard Worker
1112*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1113*57b5a4a6SAndroid Build Coastguard Workerfun main() {
1114*57b5a4a6SAndroid Build Coastguard Worker    val data = listOf(
1115*57b5a4a6SAndroid Build Coastguard Worker        OwnedProject("kotlinx.serialization", "kotlin"),
1116*57b5a4a6SAndroid Build Coastguard Worker        BasicProject("example")
1117*57b5a4a6SAndroid Build Coastguard Worker    )
1118*57b5a4a6SAndroid Build Coastguard Worker    val string = Json.encodeToString(ListSerializer(ProjectSerializer), data)
1119*57b5a4a6SAndroid Build Coastguard Worker    println(string)
1120*57b5a4a6SAndroid Build Coastguard Worker    println(Json.decodeFromString(ListSerializer(ProjectSerializer), string))
1121*57b5a4a6SAndroid Build Coastguard Worker}
1122*57b5a4a6SAndroid Build Coastguard Worker```
1123*57b5a4a6SAndroid Build Coastguard Worker
1124*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-26.kt).
1125*57b5a4a6SAndroid Build Coastguard Worker
1126*57b5a4a6SAndroid Build Coastguard WorkerNo class discriminator is added in the JSON output:
1127*57b5a4a6SAndroid Build Coastguard Worker
1128*57b5a4a6SAndroid Build Coastguard Worker```text
1129*57b5a4a6SAndroid Build Coastguard Worker[{"name":"kotlinx.serialization","owner":"kotlin"},{"name":"example"}]
1130*57b5a4a6SAndroid Build Coastguard Worker[OwnedProject(name=kotlinx.serialization, owner=kotlin), BasicProject(name=example)]
1131*57b5a4a6SAndroid Build Coastguard Worker```
1132*57b5a4a6SAndroid Build Coastguard Worker
1133*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1134*57b5a4a6SAndroid Build Coastguard Worker
1135*57b5a4a6SAndroid Build Coastguard Worker### Under the hood (experimental)
1136*57b5a4a6SAndroid Build Coastguard Worker
1137*57b5a4a6SAndroid Build Coastguard WorkerAlthough abstract serializers mentioned above can cover most of the cases, it is possible to implement similar machinery
1138*57b5a4a6SAndroid Build Coastguard Workermanually, using only the [KSerializer] class.
1139*57b5a4a6SAndroid Build Coastguard WorkerIf tweaking the abstract methods `transformSerialize`/`transformDeserialize`/`selectDeserializer` is not enough,
1140*57b5a4a6SAndroid Build Coastguard Workerthen altering `serialize`/`deserialize` is a way to go.
1141*57b5a4a6SAndroid Build Coastguard Worker
1142*57b5a4a6SAndroid Build Coastguard WorkerHere are some useful things about custom serializers with [Json]:
1143*57b5a4a6SAndroid Build Coastguard Worker
1144*57b5a4a6SAndroid Build Coastguard Worker* [Encoder] can be cast to [JsonEncoder], and [Decoder] to [JsonDecoder], if the current format is [Json].
1145*57b5a4a6SAndroid Build Coastguard Worker* `JsonDecoder` has the [decodeJsonElement][JsonDecoder.decodeJsonElement] method and `JsonEncoder`
1146*57b5a4a6SAndroid Build Coastguard Worker  has the [encodeJsonElement][JsonEncoder.encodeJsonElement] method,
1147*57b5a4a6SAndroid Build Coastguard Worker  which basically retrieve an element from and insert an element to a current position in the stream.
1148*57b5a4a6SAndroid Build Coastguard Worker* Both [`JsonDecoder`][JsonDecoder.json] and [`JsonEncoder`][JsonEncoder.json] have the `json` property,
1149*57b5a4a6SAndroid Build Coastguard Worker  which returns [Json] instance with all settings that are currently in use.
1150*57b5a4a6SAndroid Build Coastguard Worker* [Json] has the [encodeToJsonElement][Json.encodeToJsonElement] and [decodeFromJsonElement][Json.decodeFromJsonElement] methods.
1151*57b5a4a6SAndroid Build Coastguard Worker
1152*57b5a4a6SAndroid Build Coastguard WorkerGiven all that, it is possible to implement two-stage conversion `Decoder -> JsonElement -> value` or
1153*57b5a4a6SAndroid Build Coastguard Worker`value -> JsonElement -> Encoder`.
1154*57b5a4a6SAndroid Build Coastguard WorkerFor example, you can implement a fully custom serializer for the following `Response` class so that its
1155*57b5a4a6SAndroid Build Coastguard Worker`Ok` subclass is represented directly, but the `Error` subclass is represented by an object with the error message:
1156*57b5a4a6SAndroid Build Coastguard Worker
1157*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
1158*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.descriptors.*
1159*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.encoding.*
1160*57b5a4a6SAndroid Build Coastguard Worker-->
1161*57b5a4a6SAndroid Build Coastguard Worker
1162*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1163*57b5a4a6SAndroid Build Coastguard Worker@Serializable(with = ResponseSerializer::class)
1164*57b5a4a6SAndroid Build Coastguard Workersealed class Response<out T> {
1165*57b5a4a6SAndroid Build Coastguard Worker    data class Ok<out T>(val data: T) : Response<T>()
1166*57b5a4a6SAndroid Build Coastguard Worker    data class Error(val message: String) : Response<Nothing>()
1167*57b5a4a6SAndroid Build Coastguard Worker}
1168*57b5a4a6SAndroid Build Coastguard Worker
1169*57b5a4a6SAndroid Build Coastguard Workerclass ResponseSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<Response<T>> {
1170*57b5a4a6SAndroid Build Coastguard Worker    override val descriptor: SerialDescriptor = buildSerialDescriptor("Response", PolymorphicKind.SEALED) {
1171*57b5a4a6SAndroid Build Coastguard Worker        element("Ok", dataSerializer.descriptor)
1172*57b5a4a6SAndroid Build Coastguard Worker        element("Error", buildClassSerialDescriptor("Error") {
1173*57b5a4a6SAndroid Build Coastguard Worker          element<String>("message")
1174*57b5a4a6SAndroid Build Coastguard Worker        })
1175*57b5a4a6SAndroid Build Coastguard Worker    }
1176*57b5a4a6SAndroid Build Coastguard Worker
1177*57b5a4a6SAndroid Build Coastguard Worker    override fun deserialize(decoder: Decoder): Response<T> {
1178*57b5a4a6SAndroid Build Coastguard Worker        // Decoder -> JsonDecoder
1179*57b5a4a6SAndroid Build Coastguard Worker        require(decoder is JsonDecoder) // this class can be decoded only by Json
1180*57b5a4a6SAndroid Build Coastguard Worker        // JsonDecoder -> JsonElement
1181*57b5a4a6SAndroid Build Coastguard Worker        val element = decoder.decodeJsonElement()
1182*57b5a4a6SAndroid Build Coastguard Worker        // JsonElement -> value
1183*57b5a4a6SAndroid Build Coastguard Worker        if (element is JsonObject && "error" in element)
1184*57b5a4a6SAndroid Build Coastguard Worker            return Response.Error(element["error"]!!.jsonPrimitive.content)
1185*57b5a4a6SAndroid Build Coastguard Worker        return Response.Ok(decoder.json.decodeFromJsonElement(dataSerializer, element))
1186*57b5a4a6SAndroid Build Coastguard Worker    }
1187*57b5a4a6SAndroid Build Coastguard Worker
1188*57b5a4a6SAndroid Build Coastguard Worker    override fun serialize(encoder: Encoder, value: Response<T>) {
1189*57b5a4a6SAndroid Build Coastguard Worker        // Encoder -> JsonEncoder
1190*57b5a4a6SAndroid Build Coastguard Worker        require(encoder is JsonEncoder) // This class can be encoded only by Json
1191*57b5a4a6SAndroid Build Coastguard Worker        // value -> JsonElement
1192*57b5a4a6SAndroid Build Coastguard Worker        val element = when (value) {
1193*57b5a4a6SAndroid Build Coastguard Worker            is Response.Ok -> encoder.json.encodeToJsonElement(dataSerializer, value.data)
1194*57b5a4a6SAndroid Build Coastguard Worker            is Response.Error -> buildJsonObject { put("error", value.message) }
1195*57b5a4a6SAndroid Build Coastguard Worker        }
1196*57b5a4a6SAndroid Build Coastguard Worker        // JsonElement -> JsonEncoder
1197*57b5a4a6SAndroid Build Coastguard Worker        encoder.encodeJsonElement(element)
1198*57b5a4a6SAndroid Build Coastguard Worker    }
1199*57b5a4a6SAndroid Build Coastguard Worker}
1200*57b5a4a6SAndroid Build Coastguard Worker```
1201*57b5a4a6SAndroid Build Coastguard Worker
1202*57b5a4a6SAndroid Build Coastguard WorkerHaving this serializable `Response` implementation, you can take any serializable payload for its data
1203*57b5a4a6SAndroid Build Coastguard Workerand serialize or deserialize the corresponding responses:
1204*57b5a4a6SAndroid Build Coastguard Worker
1205*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1206*57b5a4a6SAndroid Build Coastguard Worker@Serializable
1207*57b5a4a6SAndroid Build Coastguard Workerdata class Project(val name: String)
1208*57b5a4a6SAndroid Build Coastguard Worker
1209*57b5a4a6SAndroid Build Coastguard Workerfun main() {
1210*57b5a4a6SAndroid Build Coastguard Worker    val responses = listOf(
1211*57b5a4a6SAndroid Build Coastguard Worker        Response.Ok(Project("kotlinx.serialization")),
1212*57b5a4a6SAndroid Build Coastguard Worker        Response.Error("Not found")
1213*57b5a4a6SAndroid Build Coastguard Worker    )
1214*57b5a4a6SAndroid Build Coastguard Worker    val string = Json.encodeToString(responses)
1215*57b5a4a6SAndroid Build Coastguard Worker    println(string)
1216*57b5a4a6SAndroid Build Coastguard Worker    println(Json.decodeFromString<List<Response<Project>>>(string))
1217*57b5a4a6SAndroid Build Coastguard Worker}
1218*57b5a4a6SAndroid Build Coastguard Worker```
1219*57b5a4a6SAndroid Build Coastguard Worker
1220*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-27.kt).
1221*57b5a4a6SAndroid Build Coastguard Worker
1222*57b5a4a6SAndroid Build Coastguard WorkerThis gives you fine-grained control on the representation of the `Response` class in the JSON output:
1223*57b5a4a6SAndroid Build Coastguard Worker
1224*57b5a4a6SAndroid Build Coastguard Worker```text
1225*57b5a4a6SAndroid Build Coastguard Worker[{"name":"kotlinx.serialization"},{"error":"Not found"}]
1226*57b5a4a6SAndroid Build Coastguard Worker[Ok(data=Project(name=kotlinx.serialization)), Error(message=Not found)]
1227*57b5a4a6SAndroid Build Coastguard Worker```
1228*57b5a4a6SAndroid Build Coastguard Worker
1229*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1230*57b5a4a6SAndroid Build Coastguard Worker
1231*57b5a4a6SAndroid Build Coastguard Worker### Maintaining custom JSON attributes
1232*57b5a4a6SAndroid Build Coastguard Worker
1233*57b5a4a6SAndroid Build Coastguard WorkerA good example of custom JSON-specific serializer would be a deserializer
1234*57b5a4a6SAndroid Build Coastguard Workerthat packs all unknown JSON properties into a dedicated field of `JsonObject` type.
1235*57b5a4a6SAndroid Build Coastguard Worker
1236*57b5a4a6SAndroid Build Coastguard WorkerLet's add `UnknownProject` &ndash; a class with the `name` property and arbitrary details flattened into the same object:
1237*57b5a4a6SAndroid Build Coastguard Worker
1238*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
1239*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.descriptors.*
1240*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.encoding.*
1241*57b5a4a6SAndroid Build Coastguard Worker-->
1242*57b5a4a6SAndroid Build Coastguard Worker
1243*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1244*57b5a4a6SAndroid Build Coastguard Workerdata class UnknownProject(val name: String, val details: JsonObject)
1245*57b5a4a6SAndroid Build Coastguard Worker```
1246*57b5a4a6SAndroid Build Coastguard Worker
1247*57b5a4a6SAndroid Build Coastguard WorkerHowever, the default plugin-generated serializer requires details
1248*57b5a4a6SAndroid Build Coastguard Workerto be a separate JSON object and that's not what we want.
1249*57b5a4a6SAndroid Build Coastguard Worker
1250*57b5a4a6SAndroid Build Coastguard WorkerTo mitigate that, write an own serializer that uses the fact that it works only with the `Json` format:
1251*57b5a4a6SAndroid Build Coastguard Worker
1252*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1253*57b5a4a6SAndroid Build Coastguard Workerobject UnknownProjectSerializer : KSerializer<UnknownProject> {
1254*57b5a4a6SAndroid Build Coastguard Worker    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("UnknownProject") {
1255*57b5a4a6SAndroid Build Coastguard Worker        element<String>("name")
1256*57b5a4a6SAndroid Build Coastguard Worker        element<JsonElement>("details")
1257*57b5a4a6SAndroid Build Coastguard Worker    }
1258*57b5a4a6SAndroid Build Coastguard Worker
1259*57b5a4a6SAndroid Build Coastguard Worker    override fun deserialize(decoder: Decoder): UnknownProject {
1260*57b5a4a6SAndroid Build Coastguard Worker        // Cast to JSON-specific interface
1261*57b5a4a6SAndroid Build Coastguard Worker        val jsonInput = decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
1262*57b5a4a6SAndroid Build Coastguard Worker        // Read the whole content as JSON
1263*57b5a4a6SAndroid Build Coastguard Worker        val json = jsonInput.decodeJsonElement().jsonObject
1264*57b5a4a6SAndroid Build Coastguard Worker        // Extract and remove name property
1265*57b5a4a6SAndroid Build Coastguard Worker        val name = json.getValue("name").jsonPrimitive.content
1266*57b5a4a6SAndroid Build Coastguard Worker        val details = json.toMutableMap()
1267*57b5a4a6SAndroid Build Coastguard Worker        details.remove("name")
1268*57b5a4a6SAndroid Build Coastguard Worker        return UnknownProject(name, JsonObject(details))
1269*57b5a4a6SAndroid Build Coastguard Worker    }
1270*57b5a4a6SAndroid Build Coastguard Worker
1271*57b5a4a6SAndroid Build Coastguard Worker    override fun serialize(encoder: Encoder, value: UnknownProject) {
1272*57b5a4a6SAndroid Build Coastguard Worker        error("Serialization is not supported")
1273*57b5a4a6SAndroid Build Coastguard Worker    }
1274*57b5a4a6SAndroid Build Coastguard Worker}
1275*57b5a4a6SAndroid Build Coastguard Worker```
1276*57b5a4a6SAndroid Build Coastguard Worker
1277*57b5a4a6SAndroid Build Coastguard WorkerNow it can be used to read flattened JSON details as `UnknownProject`:
1278*57b5a4a6SAndroid Build Coastguard Worker
1279*57b5a4a6SAndroid Build Coastguard Worker```kotlin
1280*57b5a4a6SAndroid Build Coastguard Workerfun main() {
1281*57b5a4a6SAndroid Build Coastguard Worker    println(Json.decodeFromString(UnknownProjectSerializer, """{"type":"unknown","name":"example","maintainer":"Unknown","license":"Apache 2.0"}"""))
1282*57b5a4a6SAndroid Build Coastguard Worker}
1283*57b5a4a6SAndroid Build Coastguard Worker```
1284*57b5a4a6SAndroid Build Coastguard Worker
1285*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-json-28.kt).
1286*57b5a4a6SAndroid Build Coastguard Worker
1287*57b5a4a6SAndroid Build Coastguard Worker```text
1288*57b5a4a6SAndroid Build Coastguard WorkerUnknownProject(name=example, details={"type":"unknown","maintainer":"Unknown","license":"Apache 2.0"})
1289*57b5a4a6SAndroid Build Coastguard Worker```
1290*57b5a4a6SAndroid Build Coastguard Worker
1291*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1292*57b5a4a6SAndroid Build Coastguard Worker
1293*57b5a4a6SAndroid Build Coastguard Worker---
1294*57b5a4a6SAndroid Build Coastguard Worker
1295*57b5a4a6SAndroid Build Coastguard WorkerThe next chapter covers [Alternative and custom formats (experimental)](formats.md).
1296*57b5a4a6SAndroid Build Coastguard Worker
1297*57b5a4a6SAndroid Build Coastguard Worker
1298*57b5a4a6SAndroid Build Coastguard Worker<!-- references -->
1299*57b5a4a6SAndroid Build Coastguard Worker[RFC-4627]: https://www.ietf.org/rfc/rfc4627.txt
1300*57b5a4a6SAndroid Build Coastguard Worker[BigDecimal]: https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
1301*57b5a4a6SAndroid Build Coastguard Worker
1302*57b5a4a6SAndroid Build Coastguard Worker<!-- stdlib references -->
1303*57b5a4a6SAndroid Build Coastguard Worker[Double]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/
1304*57b5a4a6SAndroid Build Coastguard Worker[Double.NaN]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/-na-n.html
1305*57b5a4a6SAndroid Build Coastguard Worker[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/
1306*57b5a4a6SAndroid Build Coastguard Worker[Map]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/
1307*57b5a4a6SAndroid Build Coastguard Worker
1308*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-core -->
1309*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
1310*57b5a4a6SAndroid Build Coastguard Worker
1311*57b5a4a6SAndroid Build Coastguard Worker[SerialName]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
1312*57b5a4a6SAndroid Build Coastguard Worker[InheritableSerialInfo]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-inheritable-serial-info/index.html
1313*57b5a4a6SAndroid Build Coastguard Worker[KSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-k-serializer/index.html
1314*57b5a4a6SAndroid Build Coastguard Worker[Serializable]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
1315*57b5a4a6SAndroid Build Coastguard Worker
1316*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.encoding -->
1317*57b5a4a6SAndroid Build Coastguard Worker
1318*57b5a4a6SAndroid Build Coastguard Worker[Encoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-encoder/index.html
1319*57b5a4a6SAndroid Build Coastguard Worker[Decoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.encoding/-decoder/index.html
1320*57b5a4a6SAndroid Build Coastguard Worker
1321*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-json -->
1322*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-json/kotlinx.serialization.json -->
1323*57b5a4a6SAndroid Build Coastguard Worker
1324*57b5a4a6SAndroid Build Coastguard Worker[Json]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html
1325*57b5a4a6SAndroid Build Coastguard Worker[Json()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json.html
1326*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html
1327*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.prettyPrint]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/pretty-print.html
1328*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.isLenient]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/is-lenient.html
1329*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.ignoreUnknownKeys]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/ignore-unknown-keys.html
1330*57b5a4a6SAndroid Build Coastguard Worker[JsonNames]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-names/index.html
1331*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.useAlternativeNames]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/use-alternative-names.html
1332*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.coerceInputValues]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/coerce-input-values.html
1333*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.encodeDefaults]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/encode-defaults.html
1334*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.explicitNulls]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/explicit-nulls.html
1335*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.allowStructuredMapKeys]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/allow-structured-map-keys.html
1336*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.allowSpecialFloatingPointValues]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/allow-special-floating-point-values.html
1337*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.classDiscriminator]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/class-discriminator.html
1338*57b5a4a6SAndroid Build Coastguard Worker[JsonClassDiscriminator]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-class-discriminator/index.html
1339*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.classDiscriminatorMode]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/class-discriminator-mode.html
1340*57b5a4a6SAndroid Build Coastguard Worker[ClassDiscriminatorMode.NONE]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-class-discriminator-mode/-n-o-n-e/index.html
1341*57b5a4a6SAndroid Build Coastguard Worker[ClassDiscriminatorMode.POLYMORPHIC]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-class-discriminator-mode/-p-o-l-y-m-o-r-p-h-i-c/index.html
1342*57b5a4a6SAndroid Build Coastguard Worker[ClassDiscriminatorMode.ALL_JSON_OBJECTS]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-class-discriminator-mode/-a-l-l_-j-s-o-n_-o-b-j-e-c-t-s/index.html
1343*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.decodeEnumsCaseInsensitive]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/decode-enums-case-insensitive.html
1344*57b5a4a6SAndroid Build Coastguard Worker[JsonBuilder.namingStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/naming-strategy.html
1345*57b5a4a6SAndroid Build Coastguard Worker[JsonNamingStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-naming-strategy/index.html
1346*57b5a4a6SAndroid Build Coastguard Worker[JsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html
1347*57b5a4a6SAndroid Build Coastguard Worker[Json.parseToJsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/parse-to-json-element.html
1348*57b5a4a6SAndroid Build Coastguard Worker[JsonPrimitive]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html
1349*57b5a4a6SAndroid Build Coastguard Worker[JsonPrimitive.content]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/content.html
1350*57b5a4a6SAndroid Build Coastguard Worker[JsonPrimitive()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive.html
1351*57b5a4a6SAndroid Build Coastguard Worker[JsonArray]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-array/index.html
1352*57b5a4a6SAndroid Build Coastguard Worker[JsonObject]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-object/index.html
1353*57b5a4a6SAndroid Build Coastguard Worker[_jsonPrimitive]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/json-primitive.html
1354*57b5a4a6SAndroid Build Coastguard Worker[_jsonArray]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/json-array.html
1355*57b5a4a6SAndroid Build Coastguard Worker[_jsonObject]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/json-object.html
1356*57b5a4a6SAndroid Build Coastguard Worker[int]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/int.html
1357*57b5a4a6SAndroid Build Coastguard Worker[intOrNull]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/int-or-null.html
1358*57b5a4a6SAndroid Build Coastguard Worker[long]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/long.html
1359*57b5a4a6SAndroid Build Coastguard Worker[longOrNull]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/long-or-null.html
1360*57b5a4a6SAndroid Build Coastguard Worker[buildJsonArray]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/build-json-array.html
1361*57b5a4a6SAndroid Build Coastguard Worker[buildJsonObject]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/build-json-object.html
1362*57b5a4a6SAndroid Build Coastguard Worker[Json.decodeFromJsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/decode-from-json-element.html
1363*57b5a4a6SAndroid Build Coastguard Worker[JsonUnquotedLiteral]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-unquoted-literal.html
1364*57b5a4a6SAndroid Build Coastguard Worker[JsonNull]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-null/index.html
1365*57b5a4a6SAndroid Build Coastguard Worker[JsonTransformingSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-transforming-serializer/index.html
1366*57b5a4a6SAndroid Build Coastguard Worker[Json.encodeToString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-string.html
1367*57b5a4a6SAndroid Build Coastguard Worker[JsonContentPolymorphicSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-content-polymorphic-serializer/index.html
1368*57b5a4a6SAndroid Build Coastguard Worker[JsonEncoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/index.html
1369*57b5a4a6SAndroid Build Coastguard Worker[JsonDecoder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/index.html
1370*57b5a4a6SAndroid Build Coastguard Worker[JsonDecoder.decodeJsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/decode-json-element.html
1371*57b5a4a6SAndroid Build Coastguard Worker[JsonEncoder.encodeJsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/encode-json-element.html
1372*57b5a4a6SAndroid Build Coastguard Worker[JsonDecoder.json]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/json.html
1373*57b5a4a6SAndroid Build Coastguard Worker[JsonEncoder.json]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/json.html
1374*57b5a4a6SAndroid Build Coastguard Worker[Json.encodeToJsonElement]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/encode-to-json-element.html
1375*57b5a4a6SAndroid Build Coastguard Worker
1376*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
1377