繁体   English   中英

Swift - 如何使用 CodingKeys 到 map 和 Int 到自定义枚举?

[英]Swift - How to use CodingKeys to map an Int to a custom enum?

我正在加载 JSON ,其中有我希望 map 到枚举的整数

//Some JSON object
{
    "id": "....",
    "name": "Some Locomotive"
    "livery": 1,
    "generation": 1
    // other variables
}

我可以使用以下方法加载此 JSON:

struct Locomotive: Codable {
    var id, name: String
    var generation: Int   
    // var livery: Int -- Replace this with my own enum (below)
    var livery: Livery?

    private enum CodingKeys: CodingKey {
        case id, name, generation
        case livery = "livery" // complains of raw value issue
    }
}

目前,生成和涂装都只是整数; 但为了让我更容易编码,我希望将 map 涂装 Integer 用于枚举; 所以而不是记住1 =绿色等; 我只能说.green

但我无法将关键涂装映射到我的枚举。

如果枚举没有原始类型,则枚举案例不能有原始值

但我确信它确实如此; 我已经将枚举中的原始值定义为私有的;

enum Livery : Codable {
    case green, red, blue, yellow
}

extension Livery {

    private enum RawValue: Int, Codable, CaseIterable {
        case green = 1, red, yellow, blue
    }

    private enum CodingKeys: Int, CodingKey {
        case green, red, blue, yellow
    }

init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let key = container.allKeys.first

        switch key {
        case .green:
            self = .green
        case .red:
            self = .red
        case .yellow:
            self = .yellow
        case .blue:
            self = .blue

        default:
            throw DecodingError.dataCorrupted(
                DecodingError.Context(
                    codingPath: container.codingPath,
                    debugDescription: "Error -- Unabled to decode."
                )
            )
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()

        switch self {
        case .green:
            try container.encode(RawValue.green)
        case .red:
            try container.encode(RawValue.red)
        case .yellow:
            try container.encode(RawValue.yellow)
        case .blue:
            try container.encode(RawValue.blue)
        }

    }
}

上面的枚举对原始值进行解码并对其进行编码。

但是,我无法将父结构中的 Livery map 分配给这个枚举,我想知道我该怎么做?

...

我想我也必须实现init(from decoder: Decoder)encode(to encoder: Encoder)到这个结构 - 特别是如果我想将来将我的数据保存到 JSON ; 但我不确定。

因此,我的查询是 - 你如何将 map 和 JSON 提供的 Integer 提供给自定义枚举,以同时保存(编码)和加载(解码)。

感谢

问题是您错误地声明了Locomotive.CodingKeys enum 所有符合CodingKey的枚举都需要具有rawValue ,但您声明CodingKeys时没有rawValue 给它一个String rawValue可以解决你的问题。

struct Locomotive: Codable {
    var id, name: String
    var generation: Int
    // var livery: Int -- Replace this with my own enum (below)
    var livery: Livery?

    private enum CodingKeys: String, CodingKey {
        case id, name, generation, livery
    }
}

您可以大大简化您的代码,您所需要的只是下面的代码。 通过说您的枚举类型为 Int swift 可以合成正确的解码代码

struct Locomotive: Codable {
    var id, name: String
    var generation: Int
    var livery: Livery?
}

enum Livery: Int, Codable {
    case green = 1, red, blue, yellow
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM