Slide 1

Slide 1 text

Performant Multiplatform Kotlin Serialization Eric Cochran KotlinConf October 5, 2018

Slide 2

Slide 2 text

Performant Multiplatform Kotlin Serialization 0.8

Slide 3

Slide 3 text

Why?

Slide 4

Slide 4 text

Get Started buildscript { repositories { maven { url 'https://kotlin.bintray.com/kotlinx' } } dependencies { classpath 'org.jetbrains.kotlinx:kotlinx-gradle-serialization-plugin:serializerVersion' } } apply plugin: 'kotlinx-serialization' dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime:serializerVersion' }

Slide 5

Slide 5 text

Get Started IJ plugin https://github.com/Kotlin/ kotlinx.serialization#working-in-intellij-idea

Slide 6

Slide 6 text

Run it @Serializable data class Data(val number: Long) JSON.stringify(Data(8L)) ProtoBuf.dump(Data(8L)) val serializer: KSerializer = Data::class.serializer()

Slide 7

Slide 7 text

Run it @Serializable data class Data(val number: Long) JSON.stringify(Data(8L)) ProtoBuf.dump(Data(8L)) val serializer: KSerializer = Data::class.serializer() JSON.stringify(serializer, Data(8L))

Slide 8

Slide 8 text

Run it @Serializable data class Data(val number: Long) val serializer: KSerializer = Data::class.serializer() val listSerializer: KSerializer> = serializer.list val setSerializer: KSerializer> = serializer.set val mapSerializer: KSerializer> = (serializer to serializer).map

Slide 9

Slide 9 text

Run it @Serializable data class Data( @Serializable(with=DifferentLongSerializer::class) val number: Long )

Slide 10

Slide 10 text

Run it @SerialInfo @Target(AnnotationTarget.PROPERTY) annotation class Special @Serializable data class Data( @Special val number: Long )

Slide 11

Slide 11 text

Run it @Serializable data class Data( @SerialName("a number") val number: Long )

Slide 12

Slide 12 text

Run it @Serializable data class Data( @Optional val number: Long )

Slide 13

Slide 13 text

Run it @Serializable data class Data( @Optional val number: Long = 8L )

Slide 14

Slide 14 text

Run it @Serializable data class Data( val number: Long? )

Slide 15

Slide 15 text

Custom Serialization @Serializable data class Data(val number: Long) { @Serializer(forClass = Data::class) companion object { override fun serialize(output: Encoder, obj: Data) { TODO() } override fun deserialize(input: Decoder): Data { TODO() } } }

Slide 16

Slide 16 text

Custom Serialization @Serializable data class Data(val number: Long) { @Serializer(forClass = Data::class) companion object { override fun serialize(output: Encoder, obj: Data) { TODO() } override fun deserialize(input: Decoder): Data { TODO() } } }

Slide 17

Slide 17 text

Custom Serialization @Serializable data class Data(val number: Long) { @Serializer(forClass = Data::class) companion object: KSerializer { override fun serialize(output: Encoder, obj: Data) { TODO() } override fun deserialize(input: Decoder): Data { TODO() } } }

Slide 18

Slide 18 text

Platform Types @Serializer(forClass = Date::class) object DateSerializer: KSerializer { override fun serialize(output: Encoder, obj: Date) { TODO() } override fun deserialize(input: Decoder): Date { TODO() } }

Slide 19

Slide 19 text

Platform Types @Serializer(forClass = Date::class) object DateSerializer: KSerializer { override fun serialize(output: Encoder, obj: Date) { TODO() } override fun deserialize(input: Decoder): Date { TODO() } }

Slide 20

Slide 20 text

KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T)

Slide 21

Slide 21 text

KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T) DeserializationStrategy - fun deserialize(input: Decoder): T

Slide 22

Slide 22 text

KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T) DeserializationStrategy - fun deserialize(input: Decoder): T val descriptor: SerialDescriptor

Slide 23

Slide 23 text

KSerialClassDesc @SerialInfo @Target(AnnotationTarget.PROPERTY) annotation class Special serialClassDesc.getAnnotationsForClass()

Slide 24

Slide 24 text

Readers and Writers data class Pair(val one: T, val two: R)

Slide 25

Slide 25 text

Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer(val t: KSerializer, val r: KSerializer): KSerializer> { }

Slide 26

Slide 26 text

Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer(val t: KSerializer, val r: KSerializer): KSerializer> { override fun load(input: Decoder): Pair { val compositeDecoder = input.beginStructure(serialClassDesc, t, r) var index = compositeDecoder.decodeElementIndex(serialClassDesc) val one = compositeDecoder.decodeSerializableElement(serialClassDesc, index, t) index = compositeDecoder.decodeElementIndex(serialClassDesc) val two = compositeDecoder.decodeSerializableElement(serialClassDesc, index, r) input.endStructure(serialClassDesc) return Pair(one, two) } }

Slide 27

Slide 27 text

Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer(val t: KSerializer, val r: KSerializer): KSerializer> { override fun save( output: Encoder, obj: Pair ) { val compositeEncoder = output.beginCollection(serialClassDesc, 2, r, t) compositeEncoder.encodeSerializableElement(serialClassDesc, 0, t, obj.one) output.encodeSerializableElement(serialClassDesc, 1, r, obj.two) output.endStructure(serialClassDesc) } }

Slide 28

Slide 28 text

Simpler Generics @Serializable class Pair(val one: R, val two: T) val serializer: KSerializer = Data::class.serializer() Pair.serializer(serializer, serializer)

Slide 29

Slide 29 text

Adapting from Java Types fun serializerByTypeToken(type: Type): KSerializer

Slide 30

Slide 30 text

Formats JSON Protobuf CBOR

Slide 31

Slide 31 text

Formats JSON - JSON.parse(deserializationStrategy, string) - JSON.stringify(serializationStrategy, data) Protobuf - ProtoBuf.load(deserializationStrategy, byteArray) - ProtoBuf.dump(serializationStrategy, data) CBOR - CBOR.load(deserializationStrategy, byteArray) - CBOR.dump(serializationStrategy, data)

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

typealias Loader = (DeserializationStrategy, T) -> Any typealias Saver = (SerializationStrategy, Any) -> T https://github.com/JakeWharton/ retrofit2-kotlinx-serialization-converter/

Slide 34

Slide 34 text

https://github.com/JakeWharton/ retrofit2-kotlinx-serialization-converter/ typealias Loader = (DeserializationStrategy, T) -> Any typealias Saver = (SerializationStrategy, Any) -> T fun stringBased( contentType: MediaType, loader: Loader, saver: Saver ): Converter.Factory

Slide 35

Slide 35 text

https://github.com/JakeWharton/ retrofit2-kotlinx-serialization-converter/ typealias Loader = (DeserializationStrategy, T) -> Any typealias Saver = (SerializationStrategy, Any) -> T fun bytesBased( contentType: MediaType, loader: Loader, saver: Saver ): Converter.Factory

Slide 36

Slide 36 text

https://github.com/JakeWharton/ retrofit2-kotlinx-serialization-converter/ val json = JSON.plain val retrofit = Retrofit.Builder() .baseUrl(baseUrl) .client(client) .addConverterFactory(stringBased(contentType, json::parse, json::stringify)) .build()

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

https://github.com/Kotlin/ kotlinx.serialization/ @Eric_Cochran