Consider the following enum and json data:
enum Options: String, Codable {
case one
case two
enum CodingKeys: String, CodingKey {
case one = "first"
case two = "second"
}
}
let jsonData = """
"first"
""".data(using: .utf8)!
My understanding of the CodingKeys
enum is that the raw value of the cases serve at the names of the keys in the json dictionary.
However, when I try to decode the data I get the following error:
let decoded = try JSONDecoder().decode(Options.self, from: jsonData)
print(decoded)
// Playground execution terminated: An error was thrown and was not caught:
// ▿ DecodingError
// ▿ dataCorrupted : Context
// - codingPath : 0 elements
// - debugDescription : "Cannot initialize Options from invalid String value first"
// - underlyingError : nil
This doesn't make any sense to me. Compare this with the following struct:
struct Size: Codable {
let size: Int
enum CodingKeys: String, CodingKey {
case size = "the_size"
}
}
let sizesJSONData = """
{ "the_size": 5 }
""".data(using: .utf8)!
let decoded = try JSONDecoder().decode(Size.self, from: sizesJSONData)
print(decoded) // success
Just as I expected, the raw value of the coding key—"the_size"—is used to decode the data. So why are enums different?
This doesn't match what the documentation says:
If the keys used in your serialized data format don't match the property names from your data type, provide alternative keys by specifying
String
as the raw-value type for theCodingKeys
enumeration. The string you use as a raw value for each enumeration case is the key name used during encoding and decoding. The association between the case name and its raw value lets you name your data structures according to the Swift API Design Guidelines rather than having to match the names, punctuation, and capitalization of the serialization format you're modeling.