Json Swift-如何使用编码键将Int映射到自定义枚举?

Json Swift-如何使用编码键将Int映射到自定义枚举?,json,swift,enums,decodable,Json,Swift,Enums,Decodable,我正在加载JSON,其中包含我希望映射到枚举的整数 //Some JSON object { "id": "....", "name": "Some Locomotive" "livery": 1, "generation": 1 // other variables } 我可以使用以下方式加载此JSON: struct Locomot

我正在加载JSON,其中包含我希望映射到枚举的整数

//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
    }
}
目前,generation和livery都是整数;但是为了使编码对我来说更容易,我希望使用将livery整数映射到枚举;因此,不要记住1=绿色等;我只能说,绿色

但我很难将密钥服务器映射到我的枚举

如果枚举没有原始类型,则枚举大小写不能有原始值

但我相信它确实如此;不过,我已经将枚举中的原始值定义为private

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映射到此枚举,我想知道如何才能做到这一点

我认为我必须将
init(从解码器:解码器)
encode(到编码器:编码器)
也实现到这个结构中——特别是如果我希望将来将数据保存到JSON;但我不确定

因此,我的问题是-如何将JSON提供的整数映射到自定义枚举以进行保存(编码)和加载(解码)


非常感谢

问题是您错误地声明了
机车.编码密钥
枚举
。所有符合
CodingKey
的枚举都需要有
rawValue
,但您声明的
CodingKey
没有
rawValue
。给它一个
字符串
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
    }
}

问题是您错误地声明了
机车.CodingKeys
枚举。所有符合
CodingKey
的枚举都需要有
rawValue
,但您声明的
CodingKey
没有
rawValue
。给它一个
字符串
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
}

你可以大大简化你的代码,你所需要的只是下面的代码。通过说您的枚举是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
}

我会试一试——也许我只是想把它复杂化。它抱怨数据格式无效。我确保两个CodingKey都有一个字符串key
private enum CodingKey:string,CodingKey{
我认为是编码键还是
init(来自解码器:解码器)
在我尝试映射itI时,Livery enum中出现了一个问题,我会尝试一下——也许我只是试图将其过度复杂化。它抱怨数据格式无效。我确保两个编码键都有一个字符串键
私有enum编码键:string,CodingKey{
我认为是编码键还是
初始化(来自decoder:decoder)
在我尝试映射它时,Livery枚举中出现了一个问题。我认为我必须手动解码并映射每个值;谢谢!当涉及到将其保存到磁盘(json文件)时;它仍然会保留整数;还是我仍然需要映射它?这很有效--我想我必须手动解码并映射每个值;谢谢!当要将其保存到磁盘(json文件)时;它仍然会保留整数;还是我仍然需要映射它?