OptionallyDecodable

OptionallyDecodable 将解码失败转换为可选值(optionals),而不是错误。

Swift 的 Codable 系统允许将对象简单地、声明式地编码为流行的序列化格式(如 JSON)并进行反序列化。

然而,在与许多 REST API 通信时,JSON 响应对象可能不像 Swift 希望的那样严格,此时 JSONDecoder 会放弃并抛出错误。 对于嵌套对象,此错误会传播到顶层对象,导致无法解码一个大型对象,仅仅因为嵌套在多层深处的一个元素意外地设置为 null 或一个迄今为止未知的枚举值。 即使您将该属性声明为可选,这也适用,因为只有 JSON null 或该值的缺失才会被解码为 nil

OptionallyDecodable 允许您注释那些不确定其确切组成的属性,原因可能是缺乏文档、错误的实现或处理 API 契约中意外的更改。

用法

只需在您认为合适的“故障点”上注释一个属性。例如,在某些情况下,您可能只想在发送未知情况时使单个枚举值变为可选,而在某些情况下,您可能希望丢弃响应的更大部分,因为它不符合您的要求,因为一个过度积极的端点返回不完整的状态对象。

给定一个 JSON 响应,例如

{
    "code": "OK",
    "result": {
        "text": "abc",
        "number": 123
    }
}

您可能希望将其解码为如下结构

enum Code: String, Decodable { case success = "OK", failure = "FAIL" }

struct Result: Decodable {
    let text: String
    let number: Int
}

struct Response: Decodable {
    let code: Code
    let result: Result
}

如果出于某种原因,API 响应突然遗漏了 textnumber 字段,则 Result 对象和整个 Response 对象都将无法解码。 通过使用 @OptionallyDecodable 注释 result 属性并将其更改为可选的 var,其解码失败将不会影响整个 Response 对象的解码。

同样,如果发现后端(可能是由于某个错误的微服务),有时会将 number 作为字符串而不是数字发送,您可以使其变为可选,并使用 @OptionallyDecodable 进行装饰。

枚举也是如此,声明枚举时,可能无法知道可能的返回代码的完整范围。 如果声明为 @OptionallyDecodablecode 将静默地转换为 nil(或 .none),而不是抛出错误。

安装

使用 Swift Package Manager

在 Xcode 中,选择 File → Swift Packages → Add Package Dependency 并粘贴到此 repo 的链接。

不使用 Swift Package Manager

只需将 OptionallyDecodable.swift 复制到您的项目中。