1

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

前任:

import kotlinx.serialization.Serializable

@Serializable

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

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

4

2 回答 2

4

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

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])
}
于 2019-10-04T06:04:21.590 回答
1

我更新了@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-07-01T10:39:57.127 回答