Swift - 如何使用 CodingKeys 将 Int 映射到自定义枚举?
Swift - How to use CodingKeys to map an Int to a custom enum?
我正在加载 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
}
}
目前世代和涂装都是整数;但是为了让我的编码更容易,我希望使用 map the livery Integer to an enum;所以与其记住 1 = 绿色,等等;我只能说 .green
但是我无法将键制服映射到我的枚举。
Enum case cannot have a raw value if the enum does not have a raw type
但我确定它确实如此;不过,我已将枚举中的原始值定义为私有;
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 提供的整数映射到自定义枚举以进行保存(编码)和加载(解码)。
谢谢
问题是您 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
}
我正在加载 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
}
}
目前世代和涂装都是整数;但是为了让我的编码更容易,我希望使用 map the livery Integer to an enum;所以与其记住 1 = 绿色,等等;我只能说 .green
但是我无法将键制服映射到我的枚举。
Enum case cannot have a raw value if the enum does not have a raw type
但我确定它确实如此;不过,我已将枚举中的原始值定义为私有;
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 提供的整数映射到自定义枚举以进行保存(编码)和加载(解码)。
谢谢
问题是您 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
}