具有多个键和关联值的可编码枚举 [英] Codable enum with multiple keys and associated values

查看:47
本文介绍了具有多个键和关联值的可编码枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到了在所有案例都有关联值时如何使枚举符合Codable的答案,但是我不清楚如何混合具有和不具有关联值的案例的枚举:

I've seen answers on how to make an enum conform to Codable when all cases have an associated value, but I'm not clear on how to mix enums that have cases with and without associated values:

???如何在给定的情况下使用同一键的多个变体?

??? How can I use multiple variations of the same key for a given case?

???如何编码/解码没有关联值的案件?

??? How do I encode/decode cases with no associated value?

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方法的假定原始字符串值作为枚举大小写的(字符串)值

Use the assumed raw string values of the init method as (string) value of the enum case

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

The Decoding Error is quite generic. You can throw more specific errors for each CodingKey

这篇关于具有多个键和关联值的可编码枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆