Мое приложение, как и многие другие приложения, извлекает JSON из API и конвертирует его с использованием нового протокола Codable
в Swift 4. В большинстве случаев это работает нормально и, как и ожидалось.Однако иногда API отправляет мне неожиданный мусор.Неправильные типы, массивы с null
внутри и тому подобное.
Проблема в том, что вовлеченные объекты могут быть большими и сложными, и когда я анализирую дочерний объект, и он выходит из строя, весь объект выходит из строя, вплоть до корня.Я включил очень простой пример игровой площадки, чтобы проиллюстрировать концепцию;фактические объекты являются более сложными.
let goodJSON = """
{
"name": "Fiona Glenanne",
"vehicles": [
{
"make": "Saab",
"model": "9-3",
"color": "Black"
},
{
"make": "Hyundai",
"model": "Genesis",
"color": "Blue"
}
]
}
"""
let goodJSONData = goodJSON.data(using: .utf8)!
let badJSON = """
{
"name": "Michael Westen",
"vehicles": {
"make": "Dodge",
"model": "Charger",
"color": "Black"
}
}
"""
let badJSONData = badJSON.data(using: .utf8)!
struct Character: Codable {
let name: String
let vehicles: [Vehicle]
}
struct Vehicle: Codable {
let make: String
let model: String
let color: String
}
do {
let goodCharacter = try JSONDecoder().decode(Character.self, from: goodJSONData)
print(goodCharacter)
} catch {
print(error)
}
do {
let badCharacter = try JSONDecoder().decode(Character.self, from: badJSONData)
print(badCharacter)
} catch DecodingError.typeMismatch(let type, let context) {
print("Got \(type); \(context.debugDescription) ** Path:\(context.codingPath)")
} catch {
print("Caught a different error: \(error)")
}
Вывод:
Character(name: "Fiona Glenanne", vehicles: [__lldb_expr_20.Vehicle(make: "Saab", model: "9-3", color: "Black"), __lldb_expr_20.Vehicle(make: "Hyundai", model: "Genesis", color: "Blue")])
Got Array<Any>; Expected to decode Array<Any> but found a dictionary instead. ** Path:[CodingKeys(stringValue: "vehicles", intValue: nil)]
vehicles
, как ожидается, будет массивом объектов, но в случае badJSON
этоэто единственный объект, который вызывает исключение .typeMismatch
и убивает синтаксический анализ прямо там.
Я ищу способ, позволяющий ошибкам, подобным этой, убить синтаксический анализ для потомкатолько объект и разрешить анализ родительского объекта для продолжения.Я пытаюсь сделать это в общем виде, поэтому мне не нужно специально рассматривать каждый объект в моем приложении, чтобы конкретно обрабатывать любые плохие данные, которые предоставляет API.Я не уверен, есть ли хоть какое-то решение для этого, мне не повезло найти что-либо, но это, несомненно, улучшит качество моей жизни, если таковое будет.Спасибо!