Расшифровка числовых ключей snake_case с помощью JSONDecoder - PullRequest
1 голос
/ 27 июня 2019

У меня есть следующий объект JSON, который нужно преобразовать в объект, используя JSONDecoder:

{
  "first_key": 3,
  "image_1000x1000": "location"
}

Это соответствует следующей модели Swift:

struct Response: Decodable {
  var firstKey: Int
  var image1000x1000: String
}

Используя JSONDecoder с опцией .convertFromSnakeCase, ключи snake_case внутри JSON преобразуются в camelCase с использованием алгоритма, определенного в документации :

Эта стратегия следует за этими шагами, чтобы преобразовать ключи JSON в случай верблюда:

  1. Прописать каждое слово, которое следует за подчеркиванием.

  2. Удалить все подчеркивания, которые не находятся в самом начале или конце строки.

  3. Объедините слова в одну строку.

Следовательно, в данном случае:

  • first_key становится firstKey (как и ожидалось)
  • image_1000x1000 должно стать image1000x1000

Однако при попытке декодировать этот ответ выдается ошибка keyNotFound для клавиши image1000x1000 ( см. Этот живой пример ):

let json = "{\"first_key\": 3, \"image_1000x1000\": \"location\"}".data(using: .utf8)!
do {
  let decoder = JSONDecoder()
  decoder.keyDecodingStrategy = .convertFromSnakeCase
  let response = try decoder.decode(Response.self, from: json)
  print(response)
} catch let e {
  print(e)
}

Что неверного в моем преобразовании верблюжьего корпуса в image_1000x1000, и почему JSONDecoder не может найти соответствующий ключ?

1 Ответ

0 голосов
/ 27 июня 2019

Вы можете увидеть, что ожидает алгоритм, запустив процесс в обратном порядке; используйте JSONEncoder для кодирования ваших данных и проверки вывода:

struct Response: Codable {
    var firstKey: Int
    var image1000x1000: String
}

let test = Response(firstKey: 10, image1000x1000: "secondKey" )

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(test)
print(String(data: data, encoding: .utf8)!)

Это даст:

{"first_key":10,"image1000x1000":"secondKey"}

Итак, если у вас есть контроль над JSON и вы можете жить с image1000x1000 в качестве ключа, то все готово. Если нет, вам придется сделать что-то вроде этого:

struct Response: Codable {
    var firstKey: Int
    var image1000x1000: String

    private enum CodingKeys: String, CodingKey {
        case image1000x1000 = "image_1000x1000"
        case firstKey = "first_key"
    }
}

Другой вариант - реализовать собственную стратегию кодирования ключей. Это может быть меньше кода. Подробнее об этом см. KeyEncodingStrategy .

...