我已经看到了在所有个案都有关联值时如何使枚举符合Codable的答案,但是我不清楚如何混合具有和不具有关联值的个案的枚举:
???如何在给定的情况下使用同一键的多个变体?
???如何编码/解码没有关联值的案件?
enum EmployeeClassification : Codable, Equatable {
case aaa
case bbb
case ccc(Int) // (year)
init?(rawValue: String?) {
guard let val = rawValue?.lowercased() else {
return nil
}
switch val {
case "aaa", "a":
self = .aaa
case "bbb":
self = .bbb
case "ccc":
self = .ccc(0)
default: return nil
}
}
// Codable
private enum CodingKeys: String, CodingKey {
case aaa // ??? how can I accept "aaa", "AAA", and "a"?
case bbb
case ccc
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let value = try? container.decode(Int.self, forKey: .ccc) {
self = .ccc(value)
return
}
// ???
// How do I decode the cases with no associated value?
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .ccc(let year):
try container.encode(year, forKey: .ccc)
default:
// ???
// How do I encode cases with no associated value?
}
}
}
答案 0 :(得分:1)
使用init方法假定的原始字符串值作为枚举大小写的(字符串)值
enum EmployeeClassification : Codable, Equatable {
case aaa
case bbb
case ccc(Int) // (year)
init?(rawValue: String?) {
guard let val = rawValue?.lowercased() else {
return nil
}
switch val {
case "aaa", "a":
self = .aaa
case "bbb":
self = .bbb
case "ccc":
self = .ccc(0)
default: return nil
}
}
// Codable
private enum CodingKeys: String, CodingKey { case aaa, bbb, ccc }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let value = try? container.decode(Int.self, forKey: .ccc) {
self = .ccc(value)
} else if let aaaValue = try? container.decode(String.self, forKey: .aaa), ["aaa", "AAA", "a"].contains(aaaValue) {
self = .aaa
} else if let bbbValue = try? container.decode(String.self, forKey: .bbb), bbbValue == "bbb" {
self = .bbb
} else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: container.codingPath, debugDescription: "Data doesn't match"))
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .aaa: try container.encode("aaa", forKey: .aaa)
case .bbb: try container.encode("bbb", forKey: .bbb)
case .ccc(let year): try container.encode(year, forKey: .ccc)
}
}
}
解码错误非常普遍。您可以为每个CodingKey抛出更具体的错误