Codable 和 CodingKeys

RPK*_*RPK 1 swift codable decodable encodable

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

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

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

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

protocol TestProtocol {
    associatedType Keys: CodingKey
}
Run Code Online (Sandbox Code Playgroud)

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

CodableCodingKeys在比什么是透过API暴露了更深层次处理?

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

rob*_*off 5

你问两个问题。我会不按顺序回答他们。

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

是的,斯威夫特编译器知道的EncodableDecodable以及CodingKey协议和具有特殊代码,为他们。

如果满足某些条件,编译器可以合成一个CodingKey兼容的enumnamed CodingKeysinit(from:)初始化器和encode(to:)方法。SE-0166中详细说明了条件:

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

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

请注意,除非您依赖编译器综合的一致性,否则CodingKey通常不必命名 -兼容类型CodingKeys甚至不必命名enum

此外,需要注意的是一个CodingKeys类型,符合CodingKey只需要有其封闭类型的每一个成员,如果你是依靠编译器合成的情况下,init(from:)encode(to:)

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

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

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

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