Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Performant Multiplatform Kotlin Serialization

Performant Multiplatform Kotlin Serialization

The promise of Kotlin is mutiplatform. Kotlin serialization is capable of making multiplatform projects share even more code. Come to learn how to get started with Kotlin serialization, how to use it with your chosen data formats, and how to integrate it with your existing frameworks. Now is the best time to hack on Kotlin serialization and learn how it can support your use cases.

Eric Cochran

October 05, 2018
Tweet

More Decks by Eric Cochran

Other Decks in Programming

Transcript

  1. 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' }
  2. Run it @Serializable data class Data(val number: Long) JSON.stringify(Data(8L)) ProtoBuf.dump(Data(8L))

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

    KSerializer<Data> = Data::class.serializer() val listSerializer: KSerializer<List<Data>> = serializer.list val setSerializer: KSerializer<Set<Data>> = serializer.set val mapSerializer: KSerializer<Map<User, User>> = (serializer to serializer).map
  4. 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() } } }
  5. 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() } } }
  6. Custom Serialization @Serializable data class Data(val number: Long) { @Serializer(forClass

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

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

    fun serialize(output: Encoder, obj: Date) { TODO() } override fun deserialize(input: Decoder): Date { TODO() } }
  9. KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T) DeserializationStrategy

    - fun deserialize(input: Decoder): T val descriptor: SerialDescriptor
  10. Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer<T, R>(val t:

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

    KSerializer<T>, val r: KSerializer<R>): KSerializer<Pair<T, R>> { override fun load(input: Decoder): Pair<T, R> { 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) } }
  12. Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer<T, R>(val t:

    KSerializer<T>, val r: KSerializer<R>): KSerializer<Pair<T, R>> { override fun save( output: Encoder, obj: Pair<T, R> ) { 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) } }
  13. Simpler Generics @Serializable class Pair<R, T>(val one: R, val two:

    T) val serializer: KSerializer<Data> = Data::class.serializer() Pair.serializer(serializer, serializer)
  14. 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)
  15. typealias Loader<T> = (DeserializationStrategy<Any>, T) -> Any typealias Saver<T> =

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

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

    Saver<T> = (SerializationStrategy<Any>, Any) -> T fun bytesBased( contentType: MediaType, loader: Loader<ByteArray>, saver: Saver<ByteArray> ): Converter.Factory
  18. 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()