2

我正在尝试实现与如何Codable使用CodingKeys枚举具有类似功能的协议。

使用Codableand CodingKeys,如果您没有在CodingKeys枚举中为对象的每个属性实现 case Codable,则会导致编译器错误,指出该对象不符合协议。

我查看了文档,我唯一能找到的与Codable( Encodableand Decodable) 协议相关的是实现func encode(to encoder: Encoder)andinit(from decoder: Decoder)功能的要求。

我得到的最接近的是定义如下协议:

protocol TestProtocol {
    associatedType Keys: CodingKey
}

这要求实现者有一个Keys符合 的属性CodingKey,但它并不强制要求所有属性都有一个案例。此外,您不能Keys像使用Codable.

是否比通过 API 公开的内容更深层次的处理CodableCodingKeys

如果没有,有没有办法在CodingKeys之外实现功能Codable

4

1 回答 1

6

你问两个问题。我会乱七八糟地回答他们。

Codable 和 CodingKeys 的处理层次是否比通过 API 公开的更深?

是的,Swift 编译器知道EncodableDecodableCodingKey协议,并为它们提供了特殊的代码。

如果满足某些条件,编译器可以合成符合标准的 named CodingKey、初始化程序和方法。SE-0166中详细说明了这些条件:enumCodingKeysinit(from:)encode(to:)

Encodable&Decodable需求也可以为某些类型自动合成:

  1. 符合Encodable其属性的类型都会Encodable自动生成String- 支持的CodingKey enum映射属性到案例名称。类似地,对于Decodable属性为 all 的类型Decodable
  2. 属于 (1) 的类型 - 以及手动提供 a CodingKey enum(命名CodingKeys、直接或通过 a typealias)的类型,其情况按名称一对一映射到Encodable/属性 -使用这些属性和键Decodable获得自动合成init(from:)和酌情encode(to:)
  3. 如果需要,既不属于 (1) 也不属于 (2) 的类型必须提供自定义键类型,并酌情提供它们自己的init(from:)encode(to:)

请注意,除非您依赖编译器综合的一致性,否则通常不必命名CodingKey-compliant 类型甚至不必命名为 an 。CodingKeysenum

此外,请注意,如果您依赖编译器来合成或,则CodingKeys符合 的类型只需要为其封闭类型的每个成员都有一个案例。CodingKeyinit(from:)encode(to:)

如果您手动实现init(from:)and encode(to:),您可以为您CodingKey的兼容类型使用任何名称,并且它只需要包含您关心的案例。CodingKey如果您只使用单值容器或无键容器进行存储,您甚至不需要符合- 标准的类型。

如果没有,有没有办法在 Codable 之外实现 CodingKeys 功能?

如果“功能”是指编译器自动合成实现的方式,那么唯一的方法是使用代码生成器(如 Sourcery 或 gyb)生成源代码并将其提供给编译器。

如果“功能”是指编译器要求每个Encodable/Decodable封闭类型成员的关键成员的方式,那么唯一的方法是运行一个单独的程序来分析您的源代码并在任何情况下丢失错误。你不能让标准的 Swift 编译器为你做这件事。

于 2019-04-16T02:38:28.910 回答