我有一个Codable类型,例如Car
,其定义为:
struct Car: Codable {
let age: Int
let color: String
}
我可以对它进行编码/解码。
在我的持久性系统中,存储对象时会为其分配一个_id
属性,该属性是一个String
,例如5cae04b533376609456d40ed
。
这样,当我从持久性存储中读取Data
并尝试对其进行解码时,其中存在表示_id
属性及其关联的String
值的额外字节。
我无法控制可以编码和存储在商店中的各种类型。对其的唯一限制是它们是Codable
。
我想做的是将从商店读取时得到的Data
(包括_id
东西)解码为类似Wrapped<T: Codable>
的类型,它将被定义为以下形式(最简单的形式):
struct Wrapped<T: Codable> {
let _id: String
let value: T
}
但是,我不确定要解决这个问题。
我做过的尝试是定义一个自定义decode
函数,但是由于我似乎无法访问T
类型的CodingKeys
,这并没有太大的意义,这使得据我所知,用这种方法不可能做到。
也许还有另一种方法可以使事情如我所愿?
答案 0 :(得分:1)
您可以为您的Wrapped
类型编写一个自定义解码函数,该函数解析出_id
,然后将解码器传递给包装的类型,以便它可以解码自己的属性:
struct Wrapped<T: Codable>: Decodable {
let _id: String
let value: T
private enum CodingKeys: String, CodingKey {
case _id
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
_id = try container.decode(String.self, forKey: ._id)
value = try T(from: decoder)
}
}
答案 1 :(得分:0)
您可以通过定义自定义_id
并从此处省略CodingKeys
来简单地声明不应解码_id
属性。如果要使用自动合成的初始化程序,还需要为未解码的属性(在您的情况下为_id
)分配一个默认值。
对于具体类型:
struct Car: Codable {
let age: Int
let color: String
let _id:Int = 0
enum CodingKeys: String, CodingKey {
case age, color
}
}
您可以为所有持久化类型实现此目标。
如果您不想为所有持久化类型创建CodingKeys
枚举,则可以遵循开始时使用的通用包装类型方法,但是您需要创建自定义的init(from:)
和{{ 1}}方法。
encode(to:)