具有多个键和关联值的可编码枚举

2024-03-01

我已经看到了有关当所有情况都有关联值时如何使枚举符合 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?
    }
}
}

使用 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 抛出更具体的错误

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有多个键和关联值的可编码枚举 的相关文章

随机推荐