Swift - 如何使用 CodingKeys 将 Int 映射到自定义枚举?



>我正在加载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
}
}

目前,基因和涂装都只是整数; 但为了让我更容易编码,我希望使用将涂装整数映射到枚举; 所以而不是记住 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)
}
}
}

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

但是,我无法将父结构中的涂装映射到此枚举,我想知道如何做到这一点?

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

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

致谢

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

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

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
}
}

最新更新