简体   繁体   中英

KotlinX Serialization of Built-in Classes

Kotlinx docs don't seem to cover this, I am wondering if there is a way to write a custom Serializer for an existing class. In my case, I need to serialize PointF and Color. For PointF, I have done this:

object MyPointFAsStringSerializer : KSerializer<MyPointF>
{
    override val descriptor: SerialDescriptor =
        buildClassSerialDescriptor("Point") {
            element<Float>("x")
            element<Float>("y")
        }

    override fun serialize(encoder: Encoder, value: MyPointF) =
        encoder.encodeStructure(descriptor) {
            encodeFloatElement(descriptor, 0, (value.x))
            encodeFloatElement(descriptor, 1, (value.y))
        }

    override fun deserialize(decoder: Decoder): MyPointF =
        decoder.decodeStructure(descriptor) {
            var x = -1f
            var y = -1f
            while (true) {
                when (val index = decodeElementIndex(descriptor)) {
                    0 -> x = decodeFloatElement(descriptor, 0)
                    1 -> y = decodeFloatElement(descriptor, 1)
                    CompositeDecoder.DECODE_DONE -> break
                    else -> error("Unexpected index: $index")
                }
            }
            MyPointF(x, y)
        }
}


@Serializable(with = MyPointFAsStringSerializer::class)
class MyPointF()
{
    var x: Float = Float.MAX_VALUE
    var y: Float = Float.MAX_VALUE

    constructor(x: Float, y: Float) : this()
    {
        this.x = x
        this.y = y
    }
    
    fun pointF () : PointF = PointF(this.x, this.y)
}

However, this approach is forcing me to go back and forth between PointF and MyPointF. I wondering how I could attach the same serializer to an existing class (ie, PointF). In Swift, I simply do this by using encodeToString , which practically tells the compiler what to do with this kind of object when serializing. But I can't seem to find a way for Kotlin. Any suggestion would be appreciated.

It's definitely possible to serialize 3rd-party classes with kotlinx serialization. You can find the docs here

object PointFAsStringSerializer : KSerializer<PointF> {
    override val descriptor: SerialDescriptor =
        buildClassSerialDescriptor("Point") {
            element<Float>("x")
            element<Float>("y")
        }

    override fun serialize(encoder: Encoder, value: PointF) =
        encoder.encodeStructure(descriptor) {
            encodeFloatElement(descriptor, 0, (value.x))
            encodeFloatElement(descriptor, 1, (value.y))
        }

    override fun deserialize(decoder: Decoder): PointF =
        decoder.decodeStructure(descriptor) {
            var x = -1f
            var y = -1f
            while (true) {
                when (val index = decodeElementIndex(descriptor)) {
                    0 -> x = decodeFloatElement(descriptor, 0)
                    1 -> y = decodeFloatElement(descriptor, 1)
                    CompositeDecoder.DECODE_DONE -> break
                    else -> error("Unexpected index: $index")
                }
            }
            PointF(x, y)
        }
}

fun main() {
    println(Json.encodeToString(PointFAsStringSerializer, PointF(1.1f, 2.2f)))
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM