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