xref: /aosp_15_r20/external/kotlinx.serialization/docs/builtin-classes.md (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1<!--- TEST_NAME BuiltinClassesTest -->
2
3# Builtin classes
4
5This is the second chapter of the [Kotlin Serialization Guide](serialization-guide.md).
6In addition to all the primitive types and strings, serialization for some classes from the Kotlin standard library,
7including the standard collections, is built into Kotlin Serialization. This chapter explains the details.
8
9**Table of contents**
10
11<!--- TOC -->
12
13* [Primitives](#primitives)
14  * [Numbers](#numbers)
15  * [Long numbers](#long-numbers)
16  * [Long numbers as strings](#long-numbers-as-strings)
17  * [Enum classes](#enum-classes)
18  * [Serial names of enum entries](#serial-names-of-enum-entries)
19* [Composites](#composites)
20  * [Pair and triple](#pair-and-triple)
21  * [Lists](#lists)
22  * [Sets and other collections](#sets-and-other-collections)
23  * [Deserializing collections](#deserializing-collections)
24  * [Maps](#maps)
25  * [Unit and singleton objects](#unit-and-singleton-objects)
26  * [Duration](#duration)
27* [Nothing](#nothing)
28
29<!--- END -->
30
31<!--- INCLUDE .*-builtin-.*
32import kotlinx.serialization.*
33import kotlinx.serialization.json.*
34-->
35
36## Primitives
37
38Kotlin Serialization has the following ten primitives:
39`Boolean`, `Byte`, `Short`, `Int`, `Long`, `Float`, `Double`, `Char`, `String`, and enums.
40The other types in Kotlin Serialization are _composite_&mdash;composed of those primitive values.
41
42### Numbers
43
44All types of integer and floating-point Kotlin numbers can be serialized.
45
46<!--- INCLUDE
47import kotlin.math.*
48-->
49
50```kotlin
51@Serializable
52class Data(
53    val answer: Int,
54    val pi: Double
55)
56
57fun main() {
58    val data = Data(42, PI)
59    println(Json.encodeToString(data))
60}
61```
62
63> You can get the full code [here](../guide/example/example-builtin-01.kt).
64
65Their natural representation in JSON is used.
66
67```text
68{"answer":42,"pi":3.141592653589793}
69```
70
71<!--- TEST -->
72
73
74### Long numbers
75
76Long integers are serializable, too.
77
78```kotlin
79@Serializable
80class Data(val signature: Long)
81
82fun main() {
83    val data = Data(0x1CAFE2FEED0BABE0)
84    println(Json.encodeToString(data))
85}
86```
87
88> You can get the full code [here](../guide/example/example-builtin-02.kt).
89
90By default they are serialized to JSON as numbers.
91
92```text
93{"signature":2067120338512882656}
94```
95
96<!--- TEST -->
97
98### Long numbers as strings
99
100The JSON output from the previous example will get decoded normally by Kotlin Serialization running on Kotlin/JS.
101However, if we try to parse this JSON by native JavaScript methods, we get this truncated result.
102
103```
104JSON.parse("{\"signature\":2067120338512882656}")
105▶ {signature: 2067120338512882700}
106```
107
108The full range of a Kotlin Long does not fit in the JavaScript number, so its precision gets lost in JavaScript.
109A common workaround is to represent long numbers with full precision using the JSON string type.
110This approach is optionally supported by Kotlin Serialization with [LongAsStringSerializer], which
111can be specified for a given Long property using the [`@Serializable`][Serializable] annotation:
112
113<!--- INCLUDE
114import kotlinx.serialization.builtins.*
115-->
116
117```kotlin
118@Serializable
119class Data(
120    @Serializable(with=LongAsStringSerializer::class)
121    val signature: Long
122)
123
124fun main() {
125    val data = Data(0x1CAFE2FEED0BABE0)
126    println(Json.encodeToString(data))
127}
128```
129
130> You can get the full code [here](../guide/example/example-builtin-03.kt).
131
132This JSON gets parsed natively by JavaScript without loss of precision.
133
134```text
135{"signature":"2067120338512882656"}
136```
137
138> The section on [Specifying serializers for a file](serializers.md#specifying-serializers-for-a-file) explains how a
139> serializer like `LongAsStringSerializer` can be specified for all properties in a file.
140
141<!--- TEST -->
142
143### Enum classes
144
145All enum classes are serializable out of the box without having to mark them `@Serializable`,
146as the following example shows.
147
148```kotlin
149// The @Serializable annotation is not needed for enum classes
150enum class Status { SUPPORTED }
151
152@Serializable
153class Project(val name: String, val status: Status)
154
155fun main() {
156    val data = Project("kotlinx.serialization", Status.SUPPORTED)
157    println(Json.encodeToString(data))
158}
159```
160
161> You can get the full code [here](../guide/example/example-builtin-04.kt).
162
163In JSON an enum gets encoded as a string.
164
165```text
166{"name":"kotlinx.serialization","status":"SUPPORTED"}
167```
168
169> Note: On Kotlin/JS and Kotlin/Native, `@Serializable` annotation is needed for enum class if you want to use it as a root object — i.e. use `encodeToString<Status>(Status.SUPPORTED)`.
170
171<!--- TEST -->
172
173### Serial names of enum entries
174
175Serial names of enum entries can be customized with the [SerialName] annotation just like
176it was shown for properties in the [Serial field names](basic-serialization.md#serial-field-names) section.
177However, in this case, the whole enum class must be marked with the [`@Serializable`][Serializable] annotation.
178
179```kotlin
180@Serializable // required because of @SerialName
181enum class Status { @SerialName("maintained") SUPPORTED }
182
183@Serializable
184class Project(val name: String, val status: Status)
185
186fun main() {
187    val data = Project("kotlinx.serialization", Status.SUPPORTED)
188    println(Json.encodeToString(data))
189}
190```
191
192> You can get the full code [here](../guide/example/example-builtin-05.kt).
193
194We see that the specified serial name is now used in the resulting JSON.
195
196```text
197{"name":"kotlinx.serialization","status":"maintained"}
198```
199
200<!--- TEST -->
201
202## Composites
203
204A number of composite types from the standard library are supported by Kotlin Serialization.
205
206### Pair and triple
207
208The simple data classes [Pair] and [Triple] from the Kotlin standard library are serializable.
209
210```kotlin
211@Serializable
212class Project(val name: String)
213
214fun main() {
215    val pair = 1 to Project("kotlinx.serialization")
216    println(Json.encodeToString(pair))
217}
218```
219
220> You can get the full code [here](../guide/example/example-builtin-06.kt).
221
222```text
223{"first":1,"second":{"name":"kotlinx.serialization"}}
224```
225
226<!--- TEST -->
227
228> Not all classes from the Kotlin standard library are serializable. In particular, ranges and the [Regex] class
229> are not serializable at the moment. Support for their serialization may be added in the future.
230
231### Lists
232
233A [List] of serializable classes can be serialized.
234
235```kotlin
236@Serializable
237class Project(val name: String)
238
239fun main() {
240    val list = listOf(
241        Project("kotlinx.serialization"),
242        Project("kotlinx.coroutines")
243    )
244    println(Json.encodeToString(list))
245}
246```
247
248> You can get the full code [here](../guide/example/example-builtin-07.kt).
249
250The result is represented as a list in JSON.
251
252```text
253[{"name":"kotlinx.serialization"},{"name":"kotlinx.coroutines"}]
254```
255
256<!--- TEST -->
257
258### Sets and other collections
259
260Other collections, like [Set], are also serializable.
261
262```kotlin
263@Serializable
264class Project(val name: String)
265
266fun main() {
267    val set = setOf(
268        Project("kotlinx.serialization"),
269        Project("kotlinx.coroutines")
270    )
271    println(Json.encodeToString(set))
272}
273```
274
275> You can get the full code [here](../guide/example/example-builtin-08.kt).
276
277[Set] is also represented as a list in JSON, like all other collections.
278
279```text
280[{"name":"kotlinx.serialization"},{"name":"kotlinx.coroutines"}]
281```
282
283<!--- TEST -->
284
285### Deserializing collections
286
287During deserialization, the type of the resulting object is determined by the static type that was specified
288in the source code&mdash;either as the type of the property or as the type parameter of the decoding function.
289The following example shows how the same JSON list of integers is deserialized into two properties of
290different Kotlin types.
291
292```kotlin
293@Serializable
294data class Data(
295    val a: List<Int>,
296    val b: Set<Int>
297)
298
299fun main() {
300    val data = Json.decodeFromString<Data>("""
301        {
302            "a": [42, 42],
303            "b": [42, 42]
304        }
305    """)
306    println(data)
307}
308```
309
310> You can get the full code [here](../guide/example/example-builtin-09.kt).
311
312Because the `data.b` property is a [Set], the duplicate values from it disappeared.
313
314```text
315Data(a=[42, 42], b=[42])
316```
317
318<!--- TEST -->
319
320### Maps
321
322A [Map] with primitive or enum keys and arbitrary serializable values can be serialized.
323
324```kotlin
325@Serializable
326class Project(val name: String)
327
328fun main() {
329    val map = mapOf(
330        1 to Project("kotlinx.serialization"),
331        2 to Project("kotlinx.coroutines")
332    )
333    println(Json.encodeToString(map))
334}
335```
336
337> You can get the full code [here](../guide/example/example-builtin-10.kt).
338
339Kotlin maps in JSON are represented as objects. In JSON object keys are always strings, so keys are encoded as strings
340even if they are numbers in Kotlin, as we can see below.
341
342```text
343{"1":{"name":"kotlinx.serialization"},"2":{"name":"kotlinx.coroutines"}}
344```
345
346<!--- TEST -->
347
348> It is a JSON-specific limitation that keys cannot be composite.
349> It can be lifted as shown in the [Allowing structured map keys](json.md#allowing-structured-map-keys) section.
350
351
352### Unit and singleton objects
353
354The Kotlin builtin `Unit` type is also serializable.
355`Unit` is a Kotlin [singleton object](https://kotlinlang.org/docs/tutorials/kotlin-for-py/objects-and-companion-objects.html),
356and is handled equally with other Kotlin objects.
357
358Conceptually, a singleton is a class with only one instance, meaning that state does not define the object,
359but the object defines its state. In JSON, objects are serialized as empty structures.
360
361```kotlin
362@Serializable
363object SerializationVersion {
364    val libraryVersion: String = "1.0.0"
365}
366
367fun main() {
368    println(Json.encodeToString(SerializationVersion))
369    println(Json.encodeToString(Unit))
370}
371```
372
373> You can get the full code [here](../guide/example/example-builtin-11.kt).
374
375While it may seem useless at first glance, this comes in handy for sealed class serialization,
376which is explained in the [Polymorphism. Objects](polymorphism.md#objects) section.
377
378```text
379{}
380{}
381```
382
383<!--- TEST -->
384
385> Serialization of objects is format specific. Other formats may represent objects differently,
386> e.g. using their fully-qualified names.
387
388### Duration
389
390Since Kotlin `1.7.20` the [Duration] class has become serializable.
391
392<!--- INCLUDE
393import kotlin.time.*
394-->
395
396```kotlin
397fun main() {
398    val duration = 1000.toDuration(DurationUnit.SECONDS)
399    println(Json.encodeToString(duration))
400}
401```
402> You can get the full code [here](../guide/example/example-builtin-12.kt).
403
404Duration is serialized as a string in the ISO-8601-2 format.
405```text
406"PT16M40S"
407```
408
409<!--- TEST -->
410
411
412## Nothing
413
414By default, [Nothing] is a serializable class. However, since there are no instances of this class, it is impossible to encode or decode its values - any attempt will cause an exception.
415
416This serializer is used when syntactically some type is needed, but it is not actually used in serialization. For example, when using parameterized polymorphic base classes:
417```kotlin
418@Serializable
419sealed class ParametrizedParent<out R> {
420    @Serializable
421    data class ChildWithoutParameter(val value: Int) : ParametrizedParent<Nothing>()
422}
423
424fun main() {
425    println(Json.encodeToString(ParametrizedParent.ChildWithoutParameter(42)))
426}
427```
428> You can get the full code [here](../guide/example/example-builtin-13.kt).
429
430When encoding, the serializer for the `Nothing` was not used
431
432```text
433{"value":42}
434```
435
436<!--- TEST -->
437
438---
439
440The next chapter covers [Serializers](serializers.md).
441
442<!-- stdlib references -->
443[Double.NaN]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/-na-n.html
444[Pair]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/
445[Triple]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-triple/
446[Regex]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/
447[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/
448[Set]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/
449[Map]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/
450[Duration]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/
451[Nothing]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-nothing.html
452
453<!--- MODULE /kotlinx-serialization-core -->
454<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
455
456[Serializable]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
457[SerialName]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
458
459<!--- MODULE /kotlinx-serialization-core -->
460<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.builtins -->
461
462[LongAsStringSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.builtins/-long-as-string-serializer/index.html
463
464<!--- END -->
465