Performant Multiplatform Kotlin Serialization Eric Cochran KotlinConf October 5, 2018
Performant Multiplatform Kotlin Serialization 0.8
Why?
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' }
Get Started IJ plugin https://github.com/Kotlin/ kotlinx.serialization#working-in-intellij-idea
Run it @Serializable data class Data(val number: Long) JSON.stringify(Data(8L)) ProtoBuf.dump(Data(8L)) val serializer: KSerializer<Data> = Data::class. serializer ()
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))
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
Run it @Serializable data class Data( @Serializable(with=DifferentLongSerializer::class) val number: Long )
Run it @SerialInfo @Target(AnnotationTarget.PROPERTY) annotation class Special @Serializable data class Data( @Special val number: Long )
Run it @Serializable data class Data( @SerialName("a number") val number: Long )
Run it @Serializable data class Data( @Optional val number: Long )
Run it @Serializable data class Data( @Optional val number: Long = 8L )
Run it @Serializable data class Data( val number: Long? )
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 () } } }
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 () } } }
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 () } } }
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 () } }
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 () } }
KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T)
KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T) DeserializationStrategy - fun deserialize(input: Decoder): T
KSerializer SerializationStrategy - fun serialize(output: Encoder, obj : T) DeserializationStrategy - fun deserialize(input: Decoder): T val descriptor: SerialDescriptor
KSerialClassDesc @SerialInfo @Target(AnnotationTarget.PROPERTY) annotation class Special serialClassDesc.getAnnotationsForClass()
Readers and Writers data class Pair<T, R>(val one: T, val two: R)
Readers and Writers @Serializer(forClass = Pair::class) class PairSerializer<T, R>(val t: KSerializer<T>, val r: KSerializer<R>): KSerializer<Pair<T, R>> { }
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) } }
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) } }
Simpler Generics @Serializable class Pair<R, T>(val one: R, val two: T) val serializer: KSerializer<Data> = Data::class. serializer () Pair.serializer(serializer, serializer)
Adapting from Java Types fun serializerByTypeToken(type: Type): KSerializer<Any>
Formats JSON Protobuf CBOR
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)
https://github.com/JakeWharton/ retrofit2-kotlinx-serialization-converter/ typealias Loader<T> = (DeserializationStrategy<Any>, T) -> Any typealias Saver<T> = (SerializationStrategy<Any>, Any) -> T
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
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
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()
https://github.com/Kotlin/ kotlinx.serialization/ @Eric_Cochran
Recommend
More recommend