Codability 0.2.1

Codability 0.2.1

Yonas Kolb 维护。



Codability

SPM Git Version Build Status license

用于在Swift中处理Codable类型的有用辅助工具

安装

Swift包管理器

将以下添加到您的Package.swift依赖关系中

.package(url: "https://github.com/yonaskolb/Codability.git", from: "0.2.0"),

然后在需要的位置导入:import Codability

辅助工具

无效元素策略

默认情况下,如果数组或字典中的单个元素失败,Decodable将抛出错误。InvalidElementStrategy是一个枚举,它允许您控制此行为。它有多个情况

  • remove:从集合中移除元素
  • fail:将使整个解码失败。这是解码器使用的默认行为
  • fallback(value):允许您以类型安全的方式提供带类型的值
  • custom((EncodingError)-> InvalidElementStrategy):让您提供基于抛出错误的具体动态行为,使您能够查找哪些键参与了错误

在解码数组或字典时,使用decodeArraydecodeDictionary函数(还有IfPresent变异体)。

InvalidElementStrategy可以通过这些函数传递,或者可以通过JSONDecoder().userInfo[.invalidElementStrategy]设置默认值,否则将使用默认的fail

给定以下JSON

{
    "array": [1, "two", 3],
    "dictionary": {
        "one": 1,
        "two": "two",
        "three": 3
    }
}
struct Object: Decodable {

    let array: [Int]
    let dictionary: [String: Int]

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: RawCodingKey.self)
        array = try container.decodeArray([Int].self, forKey: "array", invalidElementStrategy: .fallback(0))
        dictionary = try container.decodeDictionary([String: Int].self, forKey: "dictionary", invalidElementStrategy: .remove)
    }
}
let decoder = JSONDecoder()

// this will provide a default if none is passed into the decode functions
decoder.userInfo[.invalidElementStrategy] = InvalidElementStrategy<Any>.remove

let decodedObject = try decoder.decode(Object.self, from: json)
decodedObject.array == [1,0,3]
decodedObject.dictionary = ["one": 1, "three": 3]

任何Codable

使用Codable的缺点是,您不能编码和解码类型混合或未知的属性,例如[String: Any][Any]Any。这些在许多API中有时是必要的邪恶,而AnyCodable使支持这些类型变得容易。

有两种不同的方法可以使用它

作为Codable属性

这种方法的优点是您可以使用合成的Codable函数。然而,缺点是这些值必须使用AnyCodable.value解除包装。您可以通过为您的对象添加自定义的设置器和获取器来使其更容易访问。

struct AnyContainer: Codable {
    let dictionary: [String: AnyCodable]
    let array: [AnyCodable]
    let value: AnyCodable
}

自定义解码和编码函数

这允许您保留正常的结构,但需要使用decodeAnyencodeAny函数。如果您必须出于其他原因实现自定义的init(from:)encode函数,则此方法可行。在幕后,这使用AnyCodable进行编码,然后在解码的情况下将其转换为您期望的类型。

struct AnyContainer: Codable {
    let dictionary: [String: Any]
    let array: [Any]
    let value: Any
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        dictionary = try container.decodeAny(.dictionary)
        array = try container.decodeAny([Any].self, forKey: .array)
        value = try container.decodeAny(Any.self, forKey: .value)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encodeAny(dictionary, forKey: .dictionary)
        try container.encodeAny(array, forKey: .array)
        try container.encodeAny(value, forKey: .value)
    }
    
    enum CodingKeys: CodingKey {
        case dictionary
        case value
        case array
    }
}

原始CodingKey

RawCodingKey 可以用来提供动态编码键。此外,当您只需要在一个地方使用这些值时,它还无需创建标准 CodingKey 枚举。

struct Object: Decodable {

    let int: Int
    let bool: Bool

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: RawCodingKey.self)
        int = try container.decode(Int.self, forKey: "int")
        bool = try container.decode(Bool.self, forKey: "bool")
    }
}

通用解码函数

KeyedDecodingContainerUnkeyedDecodingContainer 上的默认解码函数都需要传递一个显式类型。 Codabilty 通过添加泛型函数来消除这种需求,使得您的 init(from:) 更加清晰。同时,key 参数也变为匿名。

Codabality 提供的所有辅助函数,如 decodeAnydecodeArraydecodeDictionary 函数,也包括这些泛型变体,包括 IfPresent

struct Object: Decodable {

    let int: Int?
    let bool: Bool

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: RawCodingKey.self)
        
        // old
        int = try container.decodeIfPresent(Int.self, forKey: "int")
        bool = try container.decode(Bool.self, forKey: "bool")
        
        // new
        int = try container.decodeIfPresent("int")
        bool = try container.decode("bool")
    }
}

贡献

感谢 @mattt 和 Flight-School/AnyCodableAnyCodable 的基础提供支持。许可