Swift JSONDecoder - Ключи кодирования не работают с подчеркиванием - PullRequest
0 голосов
/ 23 апреля 2019

Может кто-нибудь объяснить, почему код в части A работает, а B - нет. Это сбило меня с толку.

РАБОТА

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")

НЕ РАБОТАЕТ

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

Вторая функция покажет только кодовую клавишу без подчеркивания. Но как только я удаляю подчеркивание, в allKeys появляется ключ кодирования ...

Swift 4.2 - Xcode 10.2.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 26 апреля 2019

.convertFromSnakeCase преобразует snake_cased переменных в camelCase перед тем, как получит доступ к CodingKeys.

Если вы хотите указать CodingKeys, вы должны использовать преобразованное значение в вашем НЕ РАБОТАЮЩЕМ примере

enum CodingKeys: String, CodingKey {
    case avar1 = "avar1"
    case avar2 = "avar2"
}

Но это иллюстрирует бессмысленность CodingKeys.Так что подумайте наоборот и воспользуйтесь стратегией декодирования ключей.

Вместо удаления .convertFromSnakeCase удалите CodingKeys и инициализатор.

И поймать всегда можно Decoding ошибок.

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) }
0 голосов
/ 23 апреля 2019

Я исправил эту проблему. Это связано с проблемой, которая возникает в случае со змеей. В некоторых ситуациях могут возникнуть проблемы. Что они и почему они происходят, я не уверен. Но если у вас есть JSONDecoder с включенной стратегией Snake Case Startegy. Это удалит KeyCodings для элементов, которые закодированы с использованием змеиного регистра.

Удалив из моего JSONDecoder следующее, я смог решить проблему.

Пожалуйста, удалите следующее и вставьте Coding Strings в случай змеи, если у вас установлен этот параметр и принудительно применяете стратегию JSONDecoder с помощью .convertFromSnakeCase, он удалит строки Coding Key и будет разбит во время декодирования.

Если ваши ключи кодирования включают

codingKey = "a_json_var"

Если вы добавите convertFromSnakeCase, это полностью удалит ключ кодирования. Поэтому не указывайте текстовую строку в регистре ключей кодирования в случае змеи, иначе он сломается.

Удалить ->

decoder.keyDecodingStrategy = .convertFromSnakeCase

Если вы хотите правильно указать текстовое имя ключа кодирования.

...