我正在尝试实现一个与Codable
使用CodingKeys
枚举类似功能的协议。
使用Codable
和CodingKeys
,如果你没有在CodingKeys
枚举中为Codable
对象的每个属性实现一个案例,它会导致编译器错误,指出该对象不符合协议。
我查看了文档,我唯一能找到与Codable
(Encodable
和Decodable
)协议有关的东西是实现func encode(to encoder: Encoder)
和init(from decoder: Decoder)
函数的要求。
我得到的最接近的是如下定义协议:
protocol TestProtocol {
associatedType Keys: CodingKey
}
这要求实现者具有符合Keys
的CodingKey
属性,但它不强制要求所有属性都有一个案例。此外,您不能像使用Keys
一样将Codable
属性声明为私有属性。
Codable
和CodingKeys
的处理程度是否高于通过API公开的程度?
如果没有,有没有办法在CodingKeys
之外实现Codable
功能?
你问两个问题。我会不按时回答。
Codable和CodingKeys的处理范围是否比通过API公开的更深层次?
是的,Swift编译器知道Encodable
,Decodable
和CodingKey
协议,并为它们提供特殊代码。
如果符合某些条件,编译器可以合成一个名为CodingKey
的enum
兼容的CodingKeys
,init(from:)
初始化器和encode(to:)
方法。条件在SE-0166中详细说明:
Encodable
和Decodable
要求也可以自动合成某些类型:
- 符合
Encodable
的类型,其属性都是Encodable
,获得自动生成的String
支持的CodingKey
enum
映射属性到案例名称。类似地,Decodable
类型的属性都是Decodable
- 落入(1)的类型 - 以及手动提供
CodingKey
enum
(直接命名为CodingKeys
,或通过typealias
)的类型,其案例按名称将1对1映射到Encodable
/Decodable
属性 - 自动合成init(from:)
和encode(to:)
as适当的,使用这些属性和键- 既不属于(1)也不属于(2)的类型必须提供自定义密钥类型(如果需要)并提供自己的
init(from:)
和encode(to:)
,视情况而定
请注意,除非依赖于编译器合成的一致性,否则CodingKey
兼容类型通常不必命名为CodingKeys
或甚至是enum
。
此外,请注意,如果依靠编译器合成CodingKeys
或CodingKey
,符合init(from:)
的encode(to:)
类型只需要为其封闭类型的每个成员都有一个案例。
如果你手动实现init(from:)
和encode(to:)
,你可以使用任何名称为你的CodingKey
兼容类型,它只需要你关心的案例。如果您只使用单值容器或无键容器进行存储,则甚至不需要符合CodingKey
的类型。
如果没有,有没有办法在Codable之外实现CodingKeys功能?
如果“功能”是指编译器自动合成实现的方式,那么唯一的方法是使用代码生成器(如Sourcery或gyb)生成源代码并将其提供给编译器。
如果,通过“功能”,你的意思是编译器需要封闭类型的每个Encodable
/ Decodable
成员的密钥成员的方式,那么唯一的方法是运行一个单独的程序来分析你的源代码和错误,如果有任何情况是失踪。你不能让标准的Swift编译器为你做这件事。