【问题标题】:Kotlinx Serialization, avoid crashes on other datatypeKotlinx 序列化,避免在其他数据类型上崩溃
【发布时间】:2020-02-02 09:18:33
【问题描述】:

我在应用程序中使用外部 API,而反序列化是使用 Kotlinx 序列化包完成的,当 api 结果是多个值的 Int 数组和单个值的原始 int 时,我遇到了问题。我怎样才能避免在这个过程中崩溃。有没有更好的方法来避免崩溃或创建数据类

例如:

import kotlinx.serialization.Serializable

@Serializable

data class Bookings (val slots: List<Int>)

当插槽具有单值时 API 返回 {slots: 1} 当 slot 有多个值时 API 返回 { slots: [1,2,3,4]}

【问题讨论】:

    标签: kotlin kotlinx.serialization


    【解决方案1】:

    可以使用自定义序列化器来完成:

    import kotlinx.serialization.*
    import kotlinx.serialization.json.Json
    import kotlinx.serialization.json.JsonInput
    import kotlinx.serialization.json.JsonObject
    import kotlinx.serialization.json.int
    
    @Serializable(with = BookingsSerializer::class)
    data class Bookings(val slots: List<Int>)
    
    @Serializer(forClass = Bookings::class)
    object BookingsSerializer : KSerializer<Bookings> {
        override fun deserialize(decoder: Decoder): Bookings {
            val json = (decoder as JsonInput).decodeJson().jsonObject
            return Bookings(parseSlots(json))
        }
    
        private fun parseSlots(json: JsonObject): List<Int> {
            val slotsJson = json["slots"] ?: return emptyList()
            return try {
                slotsJson.jsonArray.content.map { it.int }
            } catch (e: Exception) {
                listOf(slotsJson.int)
            }
        }
    }
    
    @ImplicitReflectionSerializer
    fun main() {
        val json = """{"slots": 1}"""
        val result = Json.parse<Bookings>(json)
        println(result) // prints Bookings(slots=[1])
    }
    

    【讨论】:

    • 除了自定义序列化器还有其他方法
    • 至少我不知道他们:)
    • 类名好像过时了
    【解决方案2】:

    我更新了@Andrei 对 2021 年的回答,因为自 2019 年以来类和方法名称发生了一些变化:

    import kotlinx.serialization.*
    import kotlinx.serialization.json.*
    import kotlinx.serialization.encoding.Decoder
    
    @Serializable(with = BookingsSerializer::class)
    data class Bookings(val slots: List<Int>)
    
    @Serializer(forClass = Bookings::class)
    object BookingsSerializer : KSerializer<Bookings> {
        override fun deserialize(decoder: Decoder): Bookings {
            val json = (decoder as JsonDecoder).decodeJsonElement().jsonObject
            return Bookings(parseSlots(json))
        }
    
        private fun parseSlots(json: JsonObject): List<Int> {
            val slotsJson = json["slots"] ?: return emptyList()
            return try {
                slotsJson.jsonArray.map { it.jsonPrimitive.int }
            } catch (e: Exception) {
                listOf(slotsJson.jsonPrimitive.int)
            }
        }
    }
    
    val json = """{"slots": 1}"""
    val result = Json.decodeFromString<Bookings>(json)
    println(result.toString()) // prints Bookings(slots=[1])
    

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 2021-05-14
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-11
      • 2010-11-04
      • 1970-01-01
      相关资源
      最近更新 更多