Can someone please explain why code in part A works, and B does not please. It has me baffled.
WORKING
struct Coded : Codable, Hashable {
public let avar1: String
public let avar2: String
enum CodingKeys: String, CodingKey {
case avar1 = "avar1"
case avar2 = "avar2"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
print (container.allKeys)
avar1 = try container.decode(String.self, forKey: .avar1)
avar2 = try container.decode(String.self, forKey: .avar2)
}
}
let JSONStr = """
{
"avar1": "This is a string",
"avar2": "This is a string2",
}
"""
if let jsdata = JSONStr.data(using: .utf8) {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let aobj: Coded? = try? decoder.decode(Coded.self, from: jsdata)
print (aobj ?? "No object")
}
OUTPUT
[CodingKeys(stringValue: "avar1", intValue: nil), CodingKeys(stringValue: "avar2", intValue: nil)]
Coded(avar1: "This is a string", avar2: "This is a string2")
NOT WORKING
struct Coded : Codable, Hashable {
public let avar1: String
public let avar2: String
enum CodingKeys: String, CodingKey {
case avar1 = "avar1"
case avar2 = "avar_2"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
print (container.allKeys)
avar1 = try container.decode(String.self, forKey: .avar1)
avar2 = try container.decode(String.self, forKey: .avar2)
}
}
let JSONStr = """
{
"avar1": "This is a string",
"avar_2": "This is a string2",
}
"""
if let jsdata = JSONStr.data(using: .utf8) {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let aobj: Coded? = try? decoder.decode(Coded.self, from: jsdata)
print (aobj ?? "No object")
}
OUTPUT
[CodingKeys(stringValue: "avar1", intValue: nil)]
No object
The second function will only show the coding key without the underscore. But as soon as I remove the underscore it has the coding key in allKeys...
Swift 4.2 - Xcode 10.2.
Any ideas?
.convertFromSnakeCase
converts snake_cased variables to camelCase before accessing the CodingKeys
.
If you want to specify CodingKeys
you have to use the converted value in your NOT WORKING example
enum CodingKeys: String, CodingKey {
case avar1 = "avar1"
case avar2 = "avar2"
}
But this illustrates the pointlessness of the CodingKeys
. So think the other way round and take advantage of the key decoding strategy.
Rather than removing .convertFromSnakeCase
remove the CodingKeys
and the initializer.
And catch always possible Decoding
errors.
struct Coded : Codable {
public let avar1: String
public let avar2: String
}
let jsonStr = """
{
"avar1": "This is a string",
"avar_2": "This is a string2",
}
"""
let jsdata = Data(jsonStr.utf8)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let aobj = try decoder.decode(Coded.self, from: jsdata)
print(aobj)
} catch { print(error) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With