如何在Kotlinx序列化中序列化“任何”类型?

洪伯特

我有一个针对网络流量进行序列化的类。

@Serializable    
data class Packet(val dataType: String, val payload: Any)

我已经使用Java序列化通过网络发送它。接收者无法知道有效载荷的类型,但是Java对其进行了反序列化就很好了,然后我将其when(dataType)用作查找以将Any对象正确转换为正确的类型。容易疯了。

但是Kotlinx序列化(与ProtoBuf一起使用)对这种Any类型非常棘手,原因对我而言并不明显。我无法注册的序列化器Any他们在文档中推荐了一种多态方法,这种方法可以工作,但是您必须将数据包键入:

data class Packet<out T : Any>(val dataType: String, val payload: T) : SomeBaseClass<T>

但这有点烂,因为它使用内联化类型化压缩了许多代码路径,而且这并不能解决接收端不知道要尝试反序列化有效负载的类型,而不必先查看dataType字段。

这是最糟糕的22。该框架不会忽略该payload: Any字段(产生编译错误),而且我什至无法编写自定义序列化程序,因为在客户序列化程序(用于描述符)中定义element类型类型Any会产生与“未注册序列化程序”相同的运行时错误。为Any。”

米哈伊尔·纳夫塔(Mikhail Naftal)

我已经使用Java序列化通过网络发送它。接收者无法知道有效载荷的类型,但是Java将其反序列化就很好了,然后我使用when(dataType)作为查找来正确将Any对象转换为正确的类型。容易疯了。

这是因为Java序列化是相当原始的-只有一种方法可以序列化(并反序列化)对象。在kotlinx.serialization中,每个类都可以有自己的序列化策略(甚至几个)。这种灵活性是有代价的。Any可以处理的序列化(针对其子类的声明列表),但是dataType在一般情况下,无法基于部分反序列化对象的字段动态确定反序列化策略,因为无法保证首先对dataType字段进行反序列化。一些序列化格式(例如JSON或Protobuf)具有无序模式。可能会payload在之前被反序列化dataType,并且Decoder接口不允许返回/进行多次传递。

如果您确定序列化格式/消息中的属性顺序(或者感到很幸运),则可以使用以下自定义序列化器:

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*

@Serializable(with = PacketSerializer::class)
data class Packet(val dataType: String, val payload: Any)

object PacketSerializer : KSerializer<Packet> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Packet") {
        element("dataType", serialDescriptor<String>())
        element("payload", buildClassSerialDescriptor("Any"))
    }

    @Suppress("UNCHECKED_CAST")
    private val dataTypeSerializers: Map<String, KSerializer<Any>> =
        mapOf(
            "String" to serializer<String>(),
            "Int" to serializer<Int>(),
            //list them all
        ).mapValues { (_, v) -> v as KSerializer<Any> }

    private fun getPayloadSerializer(dataType: String): KSerializer<Any> = dataTypeSerializers[dataType]
        ?: throw SerializationException("Serializer for class $dataType is not registered in PacketSerializer")

    override fun serialize(encoder: Encoder, value: Packet) {
        encoder.encodeStructure(descriptor) {
            encodeStringElement(descriptor, 0, value.dataType)
            encodeSerializableElement(descriptor, 1, getPayloadSerializer(value.dataType), value.payload)
        }
    }

    @ExperimentalSerializationApi
    override fun deserialize(decoder: Decoder): Packet = decoder.decodeStructure(descriptor) {
        if (decodeSequentially()) {
            val dataType = decodeStringElement(descriptor, 0)
            val payload = decodeSerializableElement(descriptor, 1, getPayloadSerializer(dataType))
            Packet(dataType, payload)
        } else {
            require(decodeElementIndex(descriptor) == 0) { "dataType field should precede payload field" }
            val dataType = decodeStringElement(descriptor, 0)
            val payload = when (val index = decodeElementIndex(descriptor)) {
                1 -> decodeSerializableElement(descriptor, 1, getPayloadSerializer(dataType))
                CompositeDecoder.DECODE_DONE -> throw SerializationException("payload field is missing")
                else -> error("Unexpected index: $index")
            }
            Packet(dataType, payload)
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在Kotlinx序列化中序列化“任何”类型?

来自分类Dev

如何在 Typescript 中序列化/反序列化复杂对象,例如反序列化对象与序列化对象的类型相同

来自分类Dev

如何在C#中序列化/反序列化不可变列表类型

来自分类Dev

NoClassDefFoundError Kotlinx序列化

来自分类Dev

Kotlinx序列化MissingFieldException

来自分类Dev

如何在ServiceStack.OrmLite中自定义复杂类型的序列化/反序列化

来自分类Dev

Kotlinx序列化:如何规避反序列化的typeargs?

来自分类Dev

如何使用XStream序列化/反序列化类型层次结构中的对象?

来自分类Dev

如何使用Kotlinx序列化JSON的动态键

来自分类Dev

如何禁用Kotlinx序列化多态描述符?

来自分类Dev

如何在Boost序列化中创建序列化接口?

来自分类Dev

如何在序列化程序Django中序列化BigIntegerField,TextField

来自分类Dev

如何在go中序列化/反序列化地图

来自分类Dev

如何在Haskell中对通过网络发送的对象进行序列化/反序列化?

来自分类Dev

如何在Spring集成中忽略序列化器/反序列化器?

来自分类Dev

如何在Windows 8 Store App中序列化和反序列化observableCollection?

来自分类Dev

Play框架:如何在JSON中对枚举进行序列化/反序列化

来自分类Dev

如何在Kotlin中序列化/反序列化Custom对象的数组?

来自分类Dev

如何在TFS中反序列化和序列化构建过程参数

来自分类Dev

ServiceStack序列化字节[]。如何在JavaScript中反序列化?

来自分类Dev

如何在Azure Key Vault中序列化和反序列化PFX证书?

来自分类Dev

如何在TFS中反序列化和序列化构建过程参数

来自分类Dev

如何在php中反序列化jquery序列化数据?

来自分类Dev

如何使用kotlinx.serialization在Ktor中序列化Web Socket Frame.text

来自分类Dev

如何在PySpark中序列化LabeledPoint RDD?

来自分类Dev

如何在Rails中反序列化json

来自分类Dev

如何在kafka中定义多个序列化器?

来自分类Dev

如何在C#中序列化DBParameters

来自分类Dev

如何在C#中序列化对象数组?

Related 相关文章

  1. 1

    如何在Kotlinx序列化中序列化“任何”类型?

  2. 2

    如何在 Typescript 中序列化/反序列化复杂对象,例如反序列化对象与序列化对象的类型相同

  3. 3

    如何在C#中序列化/反序列化不可变列表类型

  4. 4

    NoClassDefFoundError Kotlinx序列化

  5. 5

    Kotlinx序列化MissingFieldException

  6. 6

    如何在ServiceStack.OrmLite中自定义复杂类型的序列化/反序列化

  7. 7

    Kotlinx序列化:如何规避反序列化的typeargs?

  8. 8

    如何使用XStream序列化/反序列化类型层次结构中的对象?

  9. 9

    如何使用Kotlinx序列化JSON的动态键

  10. 10

    如何禁用Kotlinx序列化多态描述符?

  11. 11

    如何在Boost序列化中创建序列化接口?

  12. 12

    如何在序列化程序Django中序列化BigIntegerField,TextField

  13. 13

    如何在go中序列化/反序列化地图

  14. 14

    如何在Haskell中对通过网络发送的对象进行序列化/反序列化?

  15. 15

    如何在Spring集成中忽略序列化器/反序列化器?

  16. 16

    如何在Windows 8 Store App中序列化和反序列化observableCollection?

  17. 17

    Play框架:如何在JSON中对枚举进行序列化/反序列化

  18. 18

    如何在Kotlin中序列化/反序列化Custom对象的数组?

  19. 19

    如何在TFS中反序列化和序列化构建过程参数

  20. 20

    ServiceStack序列化字节[]。如何在JavaScript中反序列化?

  21. 21

    如何在Azure Key Vault中序列化和反序列化PFX证书?

  22. 22

    如何在TFS中反序列化和序列化构建过程参数

  23. 23

    如何在php中反序列化jquery序列化数据?

  24. 24

    如何使用kotlinx.serialization在Ktor中序列化Web Socket Frame.text

  25. 25

    如何在PySpark中序列化LabeledPoint RDD?

  26. 26

    如何在Rails中反序列化json

  27. 27

    如何在kafka中定义多个序列化器?

  28. 28

    如何在C#中序列化DBParameters

  29. 29

    如何在C#中序列化对象数组?

热门标签

归档