Codable 和 CodingKeys

Codable and CodingKeys

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

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

我查看了文档,唯一能找到与 CodableEncodableDecodable)协议相关的是实现 [=20= 的要求] 和 init(from decoder: Decoder) 函数。

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

protocol TestProtocol {
    associatedType Keys: CodingKey
}

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

那样将 Keys 属性 声明为私有

CodableCodingKeys 的处理方式是否比通过 API 公开的内容更深?

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

你问了两个问题。我会乱序回答。

Are Codable and CodingKeys are handled at a deeper level than what is exposed through the APIs?

是的,Swift 编译器知道 EncodableDecodableCodingKey 协议,并且有针对它们的特殊代码。

如果某些条件是遇见了。 SE-0166:

中详细说明了条件

Encodable & Decodable requirements can be automatically synthesized for certain types as well:

  1. Types conforming to Encodable whose properties are all Encodable get an automatically generated String-backed CodingKey enum mapping properties to case names. Similarly for Decodable types whose properties are all Decodable
  2. Types falling into (1) — and types which manually provide a CodingKey enum (named CodingKeys, directly, or via a typealias) whose cases map 1-to-1 to Encodable/Decodable properties by name — get automatic synthesis of init(from:) and encode(to:) as appropriate, using those properties and keys
  3. Types which fall into neither (1) nor (2) will have to provide a custom key type if needed and provide their own init(from:) and encode(to:), as appropriate

请注意,符合 CodingKey 的类型通常 没有 被命名为 CodingKeys 甚至是 enum 除非你依赖于编译器综合的一致性。

此外,请注意,如果您依赖编译器来合成 init(from:),则符合 CodingKeyCodingKeys 类型只需要为其封闭类型的每个成员提供一个 case或 encode(to:).

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

If not, is there a way to implement the CodingKeys functionality outside of Codable?

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

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