xxt*_*axx 5 enums json deserialization swift codable
我必须像这样反序列化一个 JSON 字符串:
{ "name" : "John Smith", "value" : "someValue" }
Run Code Online (Sandbox Code Playgroud)
在 Swift 4 中,“value”应该是一个枚举,整个对象是一个结构体,如下所示:
struct MyType {
name: String?
value: Value?
}
Run Code Online (Sandbox Code Playgroud)
在未来的某个时候,后端可能会添加新的枚举值,所以我认为进行一些回退是明智的。
我以为我可以创建一个枚举
enum Value {
case someValue
case someOtherValue
case unknown(value: String)
}
Run Code Online (Sandbox Code Playgroud)
但我无法解决如何反序列化该枚举并使其工作。以前我只是使用String
枚举,但反序列化未知值会引发错误。
是否有一种简单的方法可以使其工作,或者我应该将值反序列化为 aString
并在结构中创建一个自定义 getter 并使用 switch 语句返回其中一种情况(甚至可能不是在结构本身中,而是在我的视图模型中)?
您可以显式地实现init(from decoder: Decoder)
和encode(to encoder: Encoder)
处理每种情况,即
struct MyType: Codable {
var name: String?
var value: Value?
enum CodingKeys: String, CodingKey {
case name
case value
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
let strValue = try values.decode(String.self, forKey: .value)
//You need to handle every case explicitly
switch strValue {
case "someValue":
value = Value.someValue
case "someOtherValue":
value = Value.someOtherValue
default:
value = Value.unknown(value: strValue)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
if let val = value {
//You need to handle every case explicitly
switch val {
case .someValue, .someOtherValue:
try container.encode(String(describing: val), forKey: .value)
case .unknown(let strValue):
try container.encode(strValue, forKey: .value)
}
}
}
}
enum Value {
case someValue
case someOtherValue
case unknown(value: String)
}
Run Code Online (Sandbox Code Playgroud)