DESIGN OF KOTLINX SERIALIZATION LEONID STARTSEV sandwwraith Copenhagen
- Slides: 98
DESIGN OF KOTLINX. SERIALIZATION LEONID STARTSEV @sandwwraith Copenhagen Denmark
At a first glance, it looks like a regular JSON library 2
At a first glance, it looks like a regular JSON library val json = Json(Json. Configuration. Stable) 3
At a first glance, it looks like a regular JSON library val json = Json(Json. Configuration. Stable) json. parse(. . . ) json. stringify(. . . ) 4
Why do we need yet another json parser? 5
Why do we need yet another json parser? These all are Java libraries 6
Multiplatform @Serializable data class Session( val id: String, val is. Service. Session: Boolean, val is. Plenum. Session: Boolean, val question. Answers: List<Question. Answer>, val speakers: List<String>, @Serial. Name("description") val description. Text: String? , val starts. At: String? , val title: String, val ends. At: String? , val category. Items: List<Int>, val room. Id: Int? ) 7
Kotlin-oriented data class Data( val data: String, val optional. Data: String = "empty" ) const val input. String = """{"data": "Foo"}""" 8
Kotlin-oriented data class Data( val data: String, val optional. Data: String = "empty" ) val data = Gson(). from. Json(input. String, Data: : class. java) // Data(data=Foo, optional. Data=null) Null for non-nullable type, definitely an error 9
Kotlin-oriented @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) val data = Json. parse(Data. serializer(), input. String) // Data(data=Foo, optional. Data=empty) OK! 10
Explicit @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) 11
Explicit @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) val serializer: KSerializer<Data> = Data. Companion. serializer() 12
Explicit @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) val serializer: KSerializer<Data> = Data. Companion. serializer() val data = Json. parse(Data. serializer(), input. String) 13
Implicit requires opt-in val data = Json. parse<List<Data>>(input. String) 14
Implicit requires opt-in val data = Json. parse<List<Data>>(input. String) This declaration is experimental and its usage must be marked with @Use. Experimental(Implicit. Reflection. Serializer: : class) 15
Implicit requires opt-in val data = Json. parse<List<Data>>(input. String) This declaration is experimental and its usage must be marked with @Use. Experimental(Implicit. Reflection. Serializer: : class) ● Doesn’t work on Native ● Doesn’t work for collections 16 https: //github. com/Kotlin/kotlinx. serialization/blob/master/runtime/common. Main/src/kotlinx/serialization/Serial. Implicits. kt#L 8
Concise val data: List<Data> = Gson(). from. Json( ) 17
Concise val data: List<Data> = Gson(). from. Json( input. Generic. String, (object: Type. Token<List<Data>>() {}). type ) A lot of ceremony 18
Concise val data: List<Data> = Json. parse( Data. serializer(). list, ) input. Generic. String Short and uniform 19 https: //github. com/Kotlin/kotlinx. serialization/blob/master/docs/runtime_usage. md#obtaining-serializers
Explicit & concise & compiletime safe @Serializable data class Complex. Data( val description: String, val data: Complex. Class ) 20
Explicit & concise & compiletime safe @Serializable data class Complex. Data( val description: String, val data: Complex. Class ) Serializer for type ‘Complex. Class’ has not been found IDE diagnostic! (from Kotlin 1. 3. 50) 21
Formats are pluggable val string. Data = Json. stringify(Data. serializer(), data) val bytes. Data 22 = Proto. Buf. dump (Data. serializer(), data)
Formats are pluggable val string. Data = Json. stringify(Data. serializer(), data) val bytes. Data = Proto. Buf. dump (Data. serializer(), data) Different formats, same API 23
Difference between serializer and format 24
Difference between serializer and format Stream of primitives Kotlin class Serialization by serializer 25 Output stream Encoding by format
Difference between serializer and format ● Optionals handling ● Class metadata Stream of primitives Kotlin class Serialization by serializer 26 Output stream Encoding by format
Difference between serializer and format ● Optionals handling ● Class metadata Stream of primitives Kotlin class Serialization by serializer 27 ● Text or bytes ● Versioning ● Schema or schemaless Output stream Encoding by format
Formats have their specific configuration val json = Json(Json. Configuration( encode. Defaults = false, unquoted = true, pretty. Print = true )) 28
Formats have their specific configuration val json = Json(Json. Configuration( encode. Defaults = false, unquoted = true, pretty. Print = true )) val protobuf = Proto. Buf() 29
Part II Behind the scenes
Why @Serializable and apply plugin: ‘. . . ’? @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) 31
Why @Serializable and apply plugin: ‘. . . ’? @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) // @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) 32
Why @Serializable and apply plugin: ‘. . . ’? apply plugin: 'kotlin-multiplatform' //apply plugin: 'kotlinx-serialization' 33
Why @Serializable and apply plugin: ‘. . . ’? apply plugin: 'kotlin-multiplatform' apply plugin: 'kotlinx-serialization' Kotlin serialization consists of acompiler plugin, which automatically produces visitor code for classes, and runtime library, which uses generated code to serialize objects without reflection. 34
What is a compiler plugin, anyway? 35
What is a compiler plugin, anyway? MAGIC 36
What is a compiler plugin, anyway? Frontend (parsing, resolution) JVM Backend 37 JS Backend Very simple scheme of Kotlin compiler Native Backend
Serialization plugin Adds. serializer() function Frontend (parsing, resolution) JVM Backend 38 JS Backend Not so simple scheme of Kotlin compiler Native Backend
Serialization plugin Adds. serializer() function Frontend (parsing, resolution) Additional code generation JVM Backend 39 JS Backend Not so simple scheme of Kotlin compiler Native Backend
So we are writing a serializer, right? 40
Difference between serializer and format Stream of primitives Kotlin class Serialization by serializer 41 Output stream Encoding by format
Which methods does Encoder have? interface Encoder { fun encode. Not. Null. Mark() fun encode. Null() fun fun fun encode. Unit() encode. Boolean(value: Boolean) encode. Byte(value: Byte) encode. Short(value: Short) encode. Int(value: Int) encode. Long(value: Long) encode. Float(value: Float) encode. Double(value: Double) encode. Char(value: Char) fun encode. String(value: String) fun encode. Enum(enum. Description: Enum. Descriptor, ordinal: Int) } 42 fun <T : Any? > encode. Serializable. Value(serializer: Serialization. Strategy<T>, value: T)
Which methods does Encoder have? interface Encoder { fun encode. Not. Null. Mark() fun encode. Null() fun fun fun encode. Unit() encode. Boolean(value: Boolean) encode. Byte(value: Byte) encode. Short(value: Short) encode. Int(value: Int) encode. Long(value: Long) encode. Float(value: Float) encode. Double(value: Double) encode. Char(value: Char) One function for each ‘primitive’ data type fun encode. String(value: String) fun encode. Enum(enum. Description: Enum. Descriptor, ordinal: Int) } 43 fun <T : Any? > encode. Serializable. Value(serializer: Serialization. Strategy<T>, value: T)
Transform to single value @Serializable data class Color(val r: Int, val g: Int, val b: Int) 44
Transform to single value @Serializable data class Color(val r: Int, val g: Int, val b: Int) "#00 FFAA" 45
Transform to single value object Single. Color. Serializer : KSerializer<Color> { override fun serialize(encoder: Encoder, obj: Color) { } } 46
Transform to single value object Single. Color. Serializer : KSerializer<Color> { override fun serialize(encoder: Encoder, obj: Color) { val code: String = obj. r. to. Hex. Code() + obj. g. to. Hex. Code() + obj. b. to. Hex. Code() } } 47
Transform to single value object Single. Color. Serializer : KSerializer<Color> { override fun serialize(encoder: Encoder, obj: Color) { val code: String = obj. r. to. Hex. Code() + obj. g. to. Hex. Code() + obj. b. to. Hex. Code() encoder. encode. String("#$code") } } 48
Transform from multiple values """{"red": 255, "green": 128, "blue": 0}""" 49
Transform from multiple values """{"red": 255, "green": 128, "blue": 0}""" @Serializable data class Color(val argb: Int) 50
Transform from multiple values override fun deserialize(decoder: Decoder): Color { var result = 0 result += decoder. decode. Int() shl 16 result += decoder. decode. Int() shl 8 result += decoder. decode. Int() shl 0 return Color(result) } 51
Transform from multiple values override fun deserialize(decoder: Decoder): Color { var result = 0 result += decoder. decode. Int() shl 16 result += decoder. decode. Int() shl 8 result += decoder. decode. Int() shl 0 return Color(result) } We don’t know whether ‘red’ goes first or not 52
How to handle structured data interface Composite. Encoder { fun encode. Int. Element(desc: Serial. Descriptor, index: Int, value: Int). . . fun encode. String. Element(desc: Serial. Descriptor, index: Int, value: String) } Containing declaration 53 Position in structure https: //github. com/Kotlin/KEEP/blob/master/proposals/extensions/serialization. md#encoder-interfaces
Transform from multiple values object Multiple. Color. Serializer : KSerializer<Color> { override fun deserialize(decoder: Decoder): Color { var result = 0 } 54 } return Color(result)
Transform from multiple values object Multiple. Color. Serializer : KSerializer<Color> { override fun deserialize(decoder: Decoder): Color { var result = 0 val decoder: Composite. Decoder = decoder. begin. Structure(descriptor) decoder. end. Structure(descriptor) return Color(result) } } 55
Transform from multiple values override fun deserialize(decoder: Decoder): Color { var result = 0 val decoder = decoder. begin. Structure(descriptor) while (true) { when (val i = decoder. decode. Element. Index(descriptor)) { } } 56 } decoder. end. Structure(descriptor) return Color(result)
Transform from multiple values override fun deserialize(decoder: Decoder): Color { var result = 0 val decoder = decoder. begin. Structure(descriptor) } 57 loop@ while (true) { when (val i = decoder. decode. Element. Index(descriptor)) { 0 -> result += decoder. decode. Int. Element(descriptor, i) shl 16 1 -> result += decoder. decode. Int. Element(descriptor, i) shl 8 2 -> result += decoder. decode. Int. Element(descriptor, i) shl 0 READ_DONE -> break@loop } } decoder. end. Structure(descriptor) return Color(result)
Difference between serializer and format Stream of primitives Kotlin class Serialization by serializer Can be auto-generated! 58 Output stream Encoding by format
How KSerializer looks inside? @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) 59
How KSerializer looks inside? 60
How KSerializer looks inside? 61 https: //github. com/Kotlin/KEEP/blob/master/proposals/extensions/serialization. md#code-generation
How KSerializer looks inside? . deserialize call begin. Structure decode. Element. Index decode[Type]Element 62
How KSerializer looks inside? . deserialize call begin. Structure decode. Element. Index decode[Type]Element end. Structure 63 Constructor call
Serial. Descriptor 64
Serial. Descriptor @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) 65
Serial. Descriptor @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) name 66 "com. myapp. Data"
Serial. Descriptor @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) Contains useful meta information 67 name "com. myapp. Data" elements[0]. name "data" elements[1]. name "optional. Data" elements[1]. is. Optional true
Part III Diving into encoding
Format interfaces don’t tell you anything about… format override fun encode. Int(value: Int) = ? ? ? override fun encode. String(value: String) = ? ? ? 69
Serializable = Parcelable? class Parcelizer(val bundle: Bundle): Named. Value. Encoder() { } 70
Serializable = Parcelable? class Parcelizer(val bundle: Bundle): Named. Value. Encoder() { override fun encode. Tagged. Int(tag: String, value: Int) { } override fun encode. Tagged. String(tag: String, value: String) { } } 71
Serializable = Parcelable class Parcelizer(val bundle: Bundle): Named. Value. Encoder() { override fun encode. Tagged. Int(tag: String, value: Int) { bundle. put. Int(tag, value) } override fun encode. Tagged. String(tag: String, value: String) { bundle. put. String(tag, value) } } 72
Serializable = Multiplatform Parcelable expect class Bundle actual typealias Bundle = android. os. Bundle class Parcelizer(val bundle: Bundle): Named. Value. Encoder() { override fun encode. Tagged. Int(tag: String, value: Int) { bundle. put. Int(tag, value) } override fun encode. Tagged. String(tag: String, value: String) { bundle. put. String(tag, value) } } 73
You even don’t have to store values anywhere 74
You even don’t have to store values anywhere val digest = Message. Digest. get. Instance("MD 5") 75
You even don’t have to store values anywhere val digest = Message. Digest. get. Instance("MD 5") class Hasher(val digest: Message. Digest): Element. Value. Encoder() { } 76
You even don’t have to store values anywhere val digest = Message. Digest. get. Instance("MD 5") class Hasher(val digest: Message. Digest): Element. Value. Encoder() { override fun encode. Byte(value: Byte) { digest. update(value) } override fun encode. String(value: String) { digest. update(value. to. Byte. Array()) } } 77
ORM done wrong class Statement. Serializer(val stmt: Prepared. Statement): Element. Value. Encoder() { } 78
ORM done wrong class Statement. Serializer(val stmt: Prepared. Statement): Element. Value. Encoder() { override fun encode. String(value: String) { stmt. set. String(i++, value) } } 79
ORM done wrong class Statement. Serializer(val stmt: Prepared. Statement): Element. Value. Encoder() { override fun encode. String(value: String) { stmt. set. String(i++, value) } } class Result. Set. Deserializer(private val rs: Result. Set): Named. Value. Decoder() { } 80
ORM done wrong class Statement. Serializer(val stmt: Prepared. Statement): Element. Value. Encoder() { override fun encode. String(value: String) { stmt. set. String(i++, value) } } class Result. Set. Deserializer(private val rs: Result. Set): Named. Value. Decoder() { override fun decode. Tagged. String(tag: String): String { return rs. get. String(tag) } } 81
Serial. Descriptor @Serializable data class Data( val data: String, val optional. Data: String = "empty" ) Contains useful meta information 82 name "com. myapp. Data" elements[0]. name "data" elements[1]. name "optional. Data" elements[1]. is. Optional true
Serial. Descriptor @Serializable data class Generic. Data<T>( val description: String, val content: T ) 83
Serial. Descriptor @Serializable data class Generic. Data<T>( val description: String, val content: T ) Generic. Data. serializer()). descriptor. dump() 84
Serial. Descriptor Generic. Data content data 85 description optional. Data
Serial. Descriptor Generic. Data com. myapp. Generic. Data { description : kotlin. String content : com. myapp. Data { data : kotlin. String optional. Data : kotlin. String } } content data 86 description optional. Data
JSON Schema 87
JSON Schema fun Json. Schema(descriptor: Serial. Descriptor): Json. Object { } 88
JSON Schema fun Json. Schema(descriptor: Serial. Descriptor): Json. Object { descriptor. element. Descriptors(). for. Each. Indexed { index, child -> } } 89
JSON Schema fun Json. Schema(descriptor: Serial. Descriptor): Json. Object { } 90 descriptor. element. Descriptors(). for. Each. Indexed { index, child -> val element. Name = descriptor. get. Element. Name(index) properties[element. Name] = Json. Schema(child) }
JSON Schema fun Json. Schema(descriptor: Serial. Descriptor): Json. Object { descriptor. element. Descriptors(). for. Each. Indexed { index, child -> val element. Name = descriptor. get. Element. Name(index) properties[element. Name] = Json. Schema(child) } } 91 val object. Data = mutable. Map. Of( "description" to Json. Literal(descriptor. name), "properties" to Json. Object(properties) ) return Json. Object(object. Data) https: //github. com/Kotlin/kotlinx. serialization/blob/master/examples/example-visitors/src/main/kotlinx/serialization/schema/Json. Schema. kt
@Serializable data class Data(val data: String, val optional. Data: String = "empty") { 92 } "description": "com. myapp. Data", "properties": { "data": { "description": "kotlin. String" }, "optional. Data": { "description": "kotlin. String" } }
Roadmap
Roadmap ✓ Core ✓ Meta information in descriptors ✓ Multiplatform polymorphism ✓ IDE diagnostics ✓ Objects and sealed classes ✓ Done
Roadmap ✓ Core ✓ Done ✓ Meta information in descriptors ✓ Multiplatform polymorphism ✓ IDE diagnostics ✓ Objects and sealed classes ➢ Inline classes ➢ In progress
Roadmap ✓ Core ✓ Done ✓ Meta information in descriptors ✓ Multiplatform polymorphism ✓ IDE diagnostics ✓ Objects and sealed classes ➢ Inline classes ➢ In progress IO Streaming & Performance tuning Planned
Roadmap ✓ Core ✓ Done ✓ Meta information in descriptors ✓ Multiplatform polymorphism ✓ IDE diagnostics ✓ Objects and sealed classes ➢ Inline classes ➢ In progress IO Streaming & Performance tuning Planned Out of experimental Kotlin 1. 4 Community driven formats
THANK YOU AND REMEMBER TO VOTE https: //github. com/Kotlin/ kotlinx. serialization Leonid Startsev@sandwwraith #Kotlin. Conf
- Kserializer
- Kotlinx serialization performance
- Brazil serialization requirements
- Can't pickle psycopg2.extensions.connection objects
- Hadoop i/o hadoop comes with a set of
- Network serialization
- Jws json serialization
- Drug supply chain security act definition
- Leonid fridman
- Leonid barenboim
- America needs its nerds essay
- Leonid gavrilov
- Leonid gavrilov
- Leonid gavrilov
- Leonid gavrilov
- Leonid afremov
- Leonid gavrilov
- Leonid gavrilov
- Trends of 1950s
- Leonid gurvits
- Leonid pryadko
- Royal library københavn
- Copenhagen interpretation
- Copenhagen criteria
- Copenhagen school five sectors of security
- Securitization copenhagen school
- Copenhagen charter cos'è
- Copenhagen charter cos'è
- Reflections copenhagen
- Internet copenhagen
- Copenhagen burnout inventory wikipedia
- Copenhagen interpretation
- Completeness in quantum mechanics
- Hera copenhagen
- Ems 2018 copenhagen
- Dr david galbreath
- Copenhagen
- Arv copenhagen
- Copenhagen golf center
- Arv copenhagen
- Visual communication design study design
- Output design in system analysis and design
- Structural and decorative design in interior design
- Decorative design types
- Partial counterbalancing psychology
- Split range
- Between subjects vs within subjects
- Between-subjects design vs within
- Matched pairs design diagram
- User interface design in system analysis and design
- Completely randomized design vs matched pairs
- Elements and principles of design ppt
- Bad design examples
- Repeated-measures design
- Dialogue design
- Byzantine floral history
- What does product and service design do
- Libidau
- Design brief design statement
- Yearbook design elements
- Stylesheet design
- Backward mapping template
- Engineering design brief
- Design brief pltw
- Job design definition
- Importance of portfolio in work immersion
- Chapter 7 work design and measurement
- Perbedaan within dan between
- Hairpin method floral design
- Define robust design
- Engineering design process quiz answers
- Elementary welding symbols
- Offshore platform design
- Oswego web design
- Web design in a nutshell
- Web design final exam
- Aerodynamics of a water bottle rocket
- Horizontal grit chamber
- Warehouse space calculation
- Memory design in vlsi
- Vlsi flow design
- Biucache
- Graduated rhythm in design
- What is graduated rhythm
- Studio art evaluation
- Vex robotics design
- Vertical transportation design
- Geometric design of railway track
- Maple sap preheater design
- Religion and society study design
- Vce psychology study design
- Vce outdoor and environmental studies
- Legal studies study design
- Vce hhd study design
- Vce extended investigation
- Drama production areas
- Anne frank set design
- What is independent variable in science
- Experimental design independent and dependent variables