首页 > 解决方案 > 如何忽略不正确的类型并使用快速编码继续 json 反序列化?

问题描述

我想知道是否有一种简单的方法来处理我的类中定义的类型与我从后端收到的类型不匹配的情况。文档很少,所以在我解析的数百个参数中,我担心某处会出现错误。

class Data : Codable {
   var Validation: Bool?
   var otherParam: String

}

例如,如果验证实际上是一个字符串而不是布尔值,那么解析似乎只是停止并在默认解码下失败。

我最初的直觉是覆盖解码并在每个键上使用可选的尝试。这是正确的想法吗?

标签: swiftcodable

解决方案


不幸的是,没有一种简单的方法可以做到这一点。类型不匹配是致命的错误,整个事情都会爆炸。您可以手动完成,但对于您的情况,这可能非常乏味。不过,只是为了展示如何做到这一点:

struct Data : Decodable {
    enum CodingKeys: CodingKey {
        case validation, otherParam
    }
    var validation: Bool?
    var otherParam: String

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.validation = try? container.decodeIfPresent(Bool.self, forKey: .validation)
        self.otherParam = try? container.decode(String.self, forKey: .otherParam) ?? ""
    }
}

显然这是非常乏味的,但是看看Sourcery可能能够生成你需要的代码。

另一种方法是解码为任意 JSON,然后提取您需要的内容。例如,请参阅RNJSON,它允许您解析任何合法的 JSON,然后对其进行查询。

(我目前正在研究一个可以处理这种情况的新解码器,但这是一个非常困难的问题。没有简单的开关可以抛出,因为在一个深度嵌套的结构中,每个都做什么并不明显级别。例如,既然otherParam不是 Optional,那么如果不是 String,应该设置成什么?如果整个 Data 类型失败,还是需要定义一个默认值 like""赋值?如果otherParam是 Bool 怎么办?是默认是真还是假?Swift 避免了隐式默认值。但是,这仍然是一个真正的问题,而且很有趣,以至于我正在研究一个玩具来探索它。最后,我怀疑对于这种特殊情况,它不会是任何比手写更好init。)


推荐阅读