问题
I have to deserialize a JSON string like this:
{ "name" : "John Smith", "value" : "someValue" }
in Swift 4, where "value" should be a enum and the whole object is a struct like:
struct MyType {
name: String?
value: Value?
}
At some point in the future, there might be new enum values added in the backend so I thought it would be smart to have some fallback.
I thought I could create a enum like
enum Value {
case someValue
case someOtherValue
case unknown(value: String)
}
but I just can't wrap my head around how to deserialize that enum and make it work. Previously I simply used a String
enum, but deserializing unknown values throws errors.
Is there a simple way to make that work or should I deserialize the value as a String
and create a custom getter in the struct with a switch statement to return one of the cases (probably not even in the struct itself but in my view model)?
回答1:
You can implement init(from decoder: Decoder)
and encode(to encoder: Encoder)
and handle every case explicitly, i.e.
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)
}
来源:https://stackoverflow.com/questions/47634348/decoding-unknown-encodable-enum-values-to-a-default