我正在使用一个 API,它可以为其属性提供不同类型的 API
属性可以是 ID 或对象
我想构建一个通用类型,用快速的编码为我处理这个问题
例:
"platforms": [
6
]
"platforms": [
{
"id": 6,
"name": "PC (Microsoft Windows)",
"slug": "win",
"url": "https://www.igdb.com/platforms/win",
"created_at": 1297639288000,
"updated_at": 1470063140518,
"website": "http://windows.microsoft.com/",
"alternative_name": "mswin"
}
]
我创建了一个名为 ObjectType 的间接枚举来处理这个问题
extension ObjectType{
enum CodingError: Error {
case decoding(String)
}
enum CodableKeys: String, CodingKey {
case Struct, Id
}
}
/**
ObjectType keeps track of struct expansion with two different 'states'
Struct OR Int64
If the request is expanded then the ObjectType will be a struct of that type. Otherwise it will be the id
@param T the struct type it should expand to, if expanded.
*/
public indirect enum ObjectType<T: Codable>: Codable {
case Struct(T)
case Id(Int64)
// decodes the response to the correct 'state', Struct or Int64.
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let standardID = try? values.decode(Int64.self) {
self = .Id(standardID)
} else if let extendedID = try? values.decode(T.self) {
self = .Struct(extendedID)
} else {
throw CodingError.decoding("Decoding Failed (dump(values))")
}
}
// encodes the response to the correct 'state', Struct or Int64.
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodableKeys.self)
switch self {
case let .Struct(extendedID):
/* this line is weird */
try container.encode(extendedID, forKey: .Struct)
case let .Id(standardID):
try container.encode(standardID, forKey: .Id)
}
}
这适用于解码,但不适用于编码结构。
调试行"try container.encode(extendedID, forKey: .struct("在 Xcode 中为 .结构大小写返回"((((",空结构。
我不明白为什么编码器在这里返回空,我做错了什么?
因此,在尝试了一堆不同的事情之后,我设法解决了它并得到了我想要的结果。
我没有正确使用编码器。 这是我的旧代码:
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodableKeys.self)
switch self {
case let .Struct(extendedID):
/* this line is weird */
try container.encode(extendedID, forKey: .Struct)
case let .Id(standardID):
try container.encode(standardID, forKey: .Id)
}
}
这是工作代码:
public func encode(to encoder: Encoder) throws {
/* var container = encoder.container(keyedBy: CodableKeys.self) */
switch self {
case let .Struct(extendedID):
try extendedID.encode(to: encoder)
/* try container.encode(extendedID, forKey: .Struct) */
case let .Id(standardID):
try standardID.encode(to: encoder)
/* try container.encode(standardID, forKey: .Id) */
}
}
该解决方案看起来非常相似,但我仍然不明白为什么这有效,而不是我以前的解决方案。