kotlinx.serialization 1.0 Leonid Startsev @sandwwraith October 13, - - PowerPoint PPT Presentation

kotlinx serialization 1 0 leonid startsev
SMART_READER_LITE
LIVE PREVIEW

kotlinx.serialization 1.0 Leonid Startsev @sandwwraith October 13, - - PowerPoint PPT Presentation

Kotlin 1.4 Online Event kotlinx.serialization 1.0 Leonid Startsev @sandwwraith October 13, 2020 Kotlin multiplatform / multi-format reflectionless serialization Kotlin multiplatform / multi-format reflectionless serialization Things well


slide-1
SLIDE 1

Kotlin 1.4 Online Event October 13, 2020 @sandwwraith

kotlinx.serialization 1.0 Leonid Startsev

slide-2
SLIDE 2

Kotlin multiplatform / multi-format reflectionless serialization

slide-3
SLIDE 3

Things we’ll cover today: 1. Introduction to kotlinx.serialization 2. Serialization APIs 3. New features in 1.0 4. Future plans 5. Setup and/or migration

Kotlin multiplatform / multi-format reflectionless serialization

slide-4
SLIDE 4

A brief introduction

slide-5
SLIDE 5

Why do we need yet another json parser?

square / moshi FasterXML / jackson google / gson

slide-6
SLIDE 6

Why do we need yet another json parser?

These are all Java libraries square / moshi FasterXML / jackson google / gson

slide-7
SLIDE 7

@Serializable data class Session( val id: String, val isServiceSession: Boolean, val isPlenumSession: Boolean, val questionAnswers: List<QuestionAnswer>, val speakers: List<String>, @SerialName("description") val descriptionText: String?, val startsAt: String?, val title: String, val endsAt: String?, val categoryItems: List<Int>, val roomId: Int? )

Multiplatform

slide-8
SLIDE 8

Kotlin-oriented

@Serializable data class Project( val name: String, val language: String = "Kotlin" ) const val inputString = """{"name":"kotlinx.serialization"}"""

slide-9
SLIDE 9

@Serializable data class Project( val name: String, val language: String = "Kotlin" ) println(Gson().fromJson(inputString, Project::class.java)) // Project(name=kotlinx.serialization, language=null) Null for a non-nullable type, definitely an error

Kotlin-oriented

slide-10
SLIDE 10

Kotlin-oriented

@Serializable data class Project( val name: String, val language: String = "Kotlin" ) println(Json.decodeFromString<Project>(inputString)) // Project(name=kotlinx.serialization, language=Kotlin) OK!

slide-11
SLIDE 11

Explicit & compile-time safe

@Serializable data class Project( val name: String, val language: String = "Kotlin" ) // not @Serializable data class User(val userName: String)

slide-12
SLIDE 12

Explicit & compile-time safe

@Serializable data class Project( val name: String, val owner: User, val language: String = "Kotlin" ) // not @Serializable data class User(val userName: String)

slide-13
SLIDE 13

Explicit & compile-time safe

@Serializable data class Project( val name: String, val owner: User, val language: String = "Kotlin" ) // not @Serializable data class User(val userName: String) Serializer for type User has not been found

slide-14
SLIDE 14

Explicit & concise

val projectsList = Gson().fromJson<List<Project>>( inputStringList, List::class.java ) println(projectsList.first()::class.java) // class com.google.gson.internal.LinkedTreeMap

slide-15
SLIDE 15

Explicit & concise

val projectsList = Gson().fromJson<List<Project>>( inputStringList, (object: TypeToken<List<Project>>() {}).type ) println(projectsList.first()::class.java) // class kotlinx.serialization.formats.json.Project

slide-16
SLIDE 16

Explicit & concise

val projectsList = Json.decodeFromString<List<Project>>(inputStringList) println(projectsList.first()::class.java) // class kotlinx.serialization.formats.json.Project

slide-17
SLIDE 17

Explicit & concise

public inline fun <reified T> typeOf(): KType

slide-18
SLIDE 18

Explicit & concise

public inline fun <reified T> typeOf(): KType val type = typeOf<Box<List<StringData>>>() println(type)

slide-19
SLIDE 19

Explicit & concise

public inline fun <reified T> typeOf(): KType val type = typeOf<Box<List<StringData>>>() println(type) "kotlinx.serialization.Box< kotlin.collections.List< kotlinx.serialization.StringData>>"

slide-20
SLIDE 20

Explicit & concise

public inline fun <reified T> serializer(): KSerializer<T>

slide-21
SLIDE 21

Explicit & concise

val serial = serializer<Box<List<StringData>>>() public inline fun <reified T> serializer(): KSerializer<T>

slide-22
SLIDE 22

Explicit & concise

val serial = serializer<Box<List<StringData>>>() // these two are equivalent val serial = Box.serializer(StringData.serializer().list) val box = Json.decodeFromString(serial, input) public inline fun <reified T> serializer(): KSerializer<T>

slide-23
SLIDE 23

www.youtube.com

Design of kotlinx.serialization  KotlinConf, 2019 by Leonid Startsev

slide-24
SLIDE 24

Many formats with similar APIs

  • JSON
  • CBOR
  • Protocol buffers
slide-25
SLIDE 25

Kotlin class Kotlin class String Byte array

slide-26
SLIDE 26

Kotlin class Kotlin class String Byte array encodeToXXX

slide-27
SLIDE 27

encodeToXXX

encodeToString

Kotlin class

encodeToByteArray

Kotlin class String Byte array

slide-28
SLIDE 28

encodeToXXX

encodeToString

Kotlin class

encodeToByteArray

Kotlin class String Byte array decodeFromXXX

slide-29
SLIDE 29

encodeToString decodeFromString

Kotlin class encodeToXXX

encodeToByteArray decodeFromString

Kotlin class String Byte array decodeFromXXX

slide-30
SLIDE 30

Future-proof configuration

slide-31
SLIDE 31

Future-proof configuration

public data class JsonConfiguration( ... val coerceInputValues: Boolean = false, val useArrayPolymorphism: Boolean = false, ... )

slide-32
SLIDE 32

Future-proof configuration

public data class JsonConfiguration( ... val coerceInputValues: Boolean = false, val coolNewJsonFeature: Boolean = false, val useArrayPolymorphism: Boolean = false, ... )

slide-33
SLIDE 33

Future-proof configuration

Exception in thread "main" java.lang.NoSuchMethodError: JsonConfiguration.<init>

slide-34
SLIDE 34

www.jakewharton.com

Public API Challenges in Kotlin by Jake Wharton

slide-35
SLIDE 35

Json(JsonConfiguration(ignoreUnknownKeys = true))

Configuring is easier

slide-36
SLIDE 36

Json(JsonConfiguration(ignoreUnknownKeys = true)) Json { ignoreUnknownKeys = true }

Configuring is easier

slide-37
SLIDE 37

val myConfig = JsonConfiguration.Default.copy(encodeDefaults = false) val myJson = Json(myConfig) val myLenientJson = Json(myConfig.copy(isLenient = true))

Copying is easier

slide-38
SLIDE 38

val myConfig = JsonConfiguration.Default.copy(encodeDefaults = false) val myJson = Json(myConfig) val myLenientJson = Json(myConfig.copy(isLenient = true))

Copying is easier

val myJson = Json { encodeDefaults = false } val myLenientJson = Json(myJson) { isLenient = true}

slide-39
SLIDE 39

1.0 release APIs

slide-40
SLIDE 40

Stable features

  • Serializing and deserializing classes from/to Strings
  • Serializable and serialization-related annotations
  • Polymorphic serialization
  • JSON tree API (including custom serialization)
  • Simple format-agnostic custom serializers
slide-41
SLIDE 41

Stable features

  • Serializing and deserializing classes from/to Strings
  • Serializable and serialization-related annotations
  • Polymorphic serialization
  • JSON tree API (including custom serialization)
  • Simple format-agnostic custom serializers

TL;DR Serialization and deserialization of @Serializable classes is stable and binary backwards compatible. New compiler plugins will support old library versions down to 1.0.

slide-42
SLIDE 42

Advanced usage patterns are experimental

  • Custom serial formats
  • Schema introspection
  • CBOR, Protobuf, HOCON, and Properties
  • ExperimentalSerializationApi
slide-43
SLIDE 43

TL;DR API for writing format-agnostic serializers, schema introspection, and implementing custom serial formats could be changed in the future. If they are, migration aids will be provided.

Advanced usage patterns are experimental

  • Custom serial formats
  • Schema introspection
  • CBOR, Protobuf, HOCON, and Properties
  • ExperimentalSerializationApi
slide-44
SLIDE 44

Internal functionality

  • kotlinx.serialization.internal.* or @InternalSerializationApi

○ If it solves your problem, it's okay. But it is not guaranteed to be compatible between releases ○ Please tell us about your use case so we can provide a stable API.

slide-45
SLIDE 45

1.0 features

slide-46
SLIDE 46

More-flexible deserialization

val json = Json { coerceInputValues = true }

slide-47
SLIDE 47

More-flexible deserialization

val json = Json { coerceInputValues = true } @Serializable data class Project( val name: String, val language: String = "Kotlin" )

slide-48
SLIDE 48

More-flexible deserialization

val json = Json { coerceInputValues = true } @Serializable data class Project( val name: String, val language: String = "Kotlin" ) println(json.decodeFromString<Project>( """{"name":"Ktor","language":null}""" ))

slide-49
SLIDE 49

More-flexible deserialization

val json = Json { coerceInputValues = true } @Serializable data class Project( val name: String, val language: String = "Kotlin" ) println(json.decodeFromString<Project>( """{"name":"Ktor","language":null}""" )) => Project(name=Ktor, language=Kotlin)

slide-50
SLIDE 50

Polymorphic deserialization

@Serializable sealed class Project { abstract val name: String abstract val language: String }

slide-51
SLIDE 51

Polymorphic deserialization

@Serializable sealed class Project { abstract val name: String abstract val language: String } @Serializable class OwnedProject(

  • verride val name: String,
  • verride val language: String,

val owner: String ): Project

slide-52
SLIDE 52

Polymorphic deserialization

@Serializable class OwnedProject(

  • verride val name: String,
  • verride val language: String,

val owner: String ): Project @Serializable class StarredProject(

  • verride val name: String,
  • verride val language: String,

val stars: Int ): Project @Serializable sealed class Project { abstract val name: String abstract val language: String }

slide-53
SLIDE 53

Polymorphic deserialization

Json.decodeFromString<Project>( """{"type":"Owned","name":"Kotlin","language":"Kotlin","owner":"JetBrains"}""" ) => OwnedProject(name=Kotlin, language=Kotlin, owner=JetBrains)

slide-54
SLIDE 54

Polymorphic deserialization

Json.decodeFromString<Project>( """{"type":"Owned","name":"Kotlin","language":"Kotlin","owner":"JetBrains"}""" ) => OwnedProject(name=Kotlin, language=Kotlin, owner=JetBrains) Json.decodeFromString<Project>( """{"type":"Starred","name":"kotlinx.serialization","language":"Kotlin", "stars":2200}""" ) => StarredProject(name=kotlinx.serialization, language=Kotlin, stars=2200)

slide-55
SLIDE 55

Polymorphic deserialization

Json.decodeFromString<Project>( """{"type":"Forked","name":"Kotlin","language":"Kotlin","forks":4100}""" ) => Polymorphic serializer was not found for class discriminator 'Forked'

  • Third-party party APIs you cannot control
  • Independent updates
slide-56
SLIDE 56

More-flexible polymorphic deserialization

val responseModule = SerializersModule { }

slide-57
SLIDE 57

More-flexible polymorphic deserialization

val responseModule = SerializersModule { polymorphic(Project::class) { } }

slide-58
SLIDE 58

More-flexible polymorphic deserialization

val responseModule = SerializersModule { polymorphic(Project::class) { default { className -> if (className != null) DefaultProject.serializer() else null } } }

=> DefaultProject(name=Kotlin, language=Kotlin)

slide-59
SLIDE 59

Future plans

slide-60
SLIDE 60

IO streaming

  • JVM-only API for java.io.* will be provided in 1.1.
  • Integration with kotlinx-io will be provided when it’s ready.
slide-61
SLIDE 61

Inline classes Work in progress

slide-62
SLIDE 62

How to set up the library

slide-63
SLIDE 63

Step 1  Compiler plugin

// Kotlin DSL plugins { kotlin("jvm") version "1.4.0" kotlin("plugin.serialization") version "1.4.0" }

slide-64
SLIDE 64

Step 1  Compiler plugin

// Groovy DSL plugins { id 'org.jetbrains.kotlin.multiplatform' version '1.4.0' id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.0' } // Kotlin DSL plugins { kotlin("jvm") version "1.4.0" kotlin("plugin.serialization") version "1.4.0" }

slide-65
SLIDE 65

Step 2  Runtime library

repositories { jcenter() } dependencies { implementation( "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0" ) }

slide-66
SLIDE 66

How to migrate

slide-67
SLIDE 67

Step 0

slide-68
SLIDE 68

Step 1  Alt+Enter

slide-69
SLIDE 69

Step 2  Replace with

slide-70
SLIDE 70

It’s dangerous to go it alone, take this

Visit https://github.com/Kotlin/kotlinx.serialization for big migration guide and changelog import kotlinx.serialization.* import kotlinx.serialization.builtins.* import kotlinx.serialization.json.* import kotlinx.serialization.modules.*

slide-71
SLIDE 71

Thanks! Have a nice Kotlin

@sandwwraith github.com/Kotlin/ kotlinx.serialization