【问题标题】:Kotlinx Serialization - Custom serializer to ignore null valueKotlinx 序列化 - 自定义序列化程序以忽略空值
【发布时间】:2020-01-23 04:06:24
【问题描述】:

假设我有这样的课程:

@Serializable
data class MyClass(
    @SerialName("a") val a: String?,
    @SerialName("b") val b: String
)

假设anull 并且b 的值是“b 值”,那么Json.stringify(MyClass.serializer(), this) 产生:

{ "a": null, "b": "b value" }

基本上如果anull,我想得到这个:

{ "b": "b value" }

通过一些研究,我发现目前无法通过 Kotlinx 序列化开箱即用,因此我试图构建一个自定义序列化程序以显式忽略 null 值。我按照here 的指南进行操作,但无法做出正确的指南。

有人可以帮我解释一下吗?谢谢。

【问题讨论】:

    标签: kotlin serialization json-deserialization kotlinx.serialization


    【解决方案1】:

    JsonConfiguration 中使用encodeDefaults = false 属性,它不会序列化空值(或其他可选值)

    【讨论】:

    • 这仅在您想忽略并非总是如此的所有默认值时才有效。一个例子是 WooCommerce,其中有一个“variation_id”,如果它不存在,则不应将其作为订单项传递给订单,因此理想的路径是将其设置为 null,但 WooCommerce 不接受 null 作为价值。在这种情况下,更细粒度的控制可以说“如果尚未设置则忽略此值”或“如果它为空则忽略此值”。
    【解决方案2】:

    试试这个(未测试,仅基于改编示例):

    @Serializable
    data class MyClass(val a: String?, val b: String) {
        @Serializer(forClass = MyClass::class)
            companion object : KSerializer<MyClass> {
            override val descriptor: SerialDescriptor = object : SerialClassDescImpl("MyClass") {
                init {
                    addElement("a")
                    addElement("b")
                }
            }
    
            override fun serialize(encoder: Encoder, obj: MyClass) {
                encoder.beginStructure(descriptor).run {
                    obj.a?.let { encodeStringElement(descriptor, 0, obj.a) }
                    encodeStringElement(descriptor, 1, obj.b)
                    endStructure(descriptor)
                }
            }
    
            override fun deserialize(decoder: Decoder): MyClass {
                var a: String? = null
                var b = ""
    
                decoder.beginStructure(descriptor).run {
                    loop@ while (true) {
                        when (val i = decodeElementIndex(descriptor)) {
                            CompositeDecoder.READ_DONE -> break@loop
                            0 -> a = decodeStringElement(descriptor, i)
                            1 -> b = decodeStringElement(descriptor, i)
                            else -> throw SerializationException("Unknown index $i")
                        }
                    }
                    endStructure(descriptor)
                }
    
                return MyClass(a, b)
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      JsonConfiguration弃用,支持 Json {} 构建器,因为 kotlinx.serialization 1.0.0-RC 根据其changelog

      现在你必须像这样编写代码:

      val json = Json { encodeDefaults = false }
      val body = json.encodeToString(someSerializableObject)
      

      【讨论】:

        【解决方案4】:

        你可以使用explicitNulls = false

        示例:

        @OptIn(ExperimentalSerializationApi::class)
        val format = Json { explicitNulls = false }
            
        @Serializable
        data class Project(
            val name: String,
            val language: String,
            val version: String? = "1.3.0",
            val website: String?,
        )
            
        fun main() {
            val data = Project("kotlinx.serialization", "Kotlin", null, null)
            val json = format.encodeToString(data)
            println(json) // {"name":"kotlinx.serialization","language":"Kotlin"}
        }
        

        https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#explicit-nulls

        【讨论】:

          猜你喜欢
          • 2020-02-15
          • 2015-11-15
          • 1970-01-01
          • 2014-09-20
          • 2016-05-17
          • 2019-05-21
          • 2013-02-17
          • 1970-01-01
          • 2021-03-11
          相关资源
          最近更新 更多