Сделать так, чтобы Swift JSONDecoder не терпел неудачу, если тип ключа не соответствует

У меня есть одна простая структура:

struct Object: Codable {
    let year: Int?
    …
}

Это нормально, когда JSON декодируется как { "year": 10, … } или не year в JSON.
Но декодировать не удастся, если JSON имеет другой тип ключа: { "year": "maybe string value" }

Как я мог не завершить процесс декодирования, если тип не соответствует необязательному свойству?

Спасибо.


person user25917    schedule 28.06.2019    source источник


Ответы (1)


Реализовать init(from:) в struct Object. Создайте enum CodingKeys и добавьте cases для всех properties, которые вы хотите проанализировать.

В init(from:) проанализируйте keys вручную и проверьте, может ли year из JSON быть декодировано как Int. Если да, назначьте его свойству Object's year, иначе не делайте этого.

struct Object: Codable {
    var year: Int?

    enum CodingKeys: String,CodingKey {
        case year
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        if let yr = try? values.decodeIfPresent(Int.self, forKey: .year) {
            year = yr
        }
    }
}

Проанализируйте ответ JSON следующим образом:

do {
    let object = try JSONDecoder().decode(Object.self, from: data)
    print(object)
} catch {
    print(error)
}

Пример:

  1. Если JSON равен { "year": "10"}, object равен: Object(year: nil)
  2. Если JSON равен { "year": 10}, object равен: Object(year: Optional(10))
person PGDev    schedule 28.06.2019
comment
Могу ли я настроить JSONDecoder, чтобы это произошло, но не настроить структуру Codable? Больно реализовывать все подобные вещи. - person user25917; 28.06.2019
comment
Да это оно. Лучше, чтобы вы предпочли изменить ответ API, чтобы вернуть согласованные типы для ключей. - person PGDev; 28.06.2019
comment
Другого способа справиться с этим нет. Вы не можете настроить JSONDecoder для такой реализации. - person PGDev; 28.06.2019
comment
Я использую Scripting Bridge для связи с другими приложениями Mac через Apple Event. Так что я не могу изменить ответ. В лицо должен сказать, что вся реакция с другой стороны через несколько раз изменится. Но небольшое изменение должно быть в порядке. Это пользователь ожидает. - person user25917; 28.06.2019
comment
Спасибо за ответ. Я надеюсь, что Apple улучшит декодер, чтобы сделать для нас больше пользовательских опций. - person user25917; 28.06.2019