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