gpt4 book ai didi

swift 可编码 : Continue parsing object after nested object error

转载 作者:行者123 更新时间:2023-11-28 14:12:44 28 4
gpt4 key购买 nike

我的应用程序,就像很多应用程序一样,从 API 检索 JSON 并使用 Swift 4 中新的 Codable 协议(protocol)转换它。大多数时候,这工作正常并且符合预期。但是,有时 API 会向我发送意想不到的垃圾。不正确的类型,内部只有 null 的数组,诸如此类。

问题是涉及的对象可能又大又复杂,当我解析一个子对象时它失败了,整个对象都失败了,一直到根。我包括了一个非常简单的 Playground 示例来说明这个概念;涉及的实际对象要复杂得多。

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 提供的任何不良数据。我不确定是否有解决方案,我还没有找到任何解决方案,但如果有的话肯定会提高我的生活质量。谢谢!

最佳答案

您可以尝试按照评论中的建议自定义 init(from decoder: Decoder),它会是这样的,

struct Character: Codable {
let name: String
let vehicles: [Vehicle]
private enum CodingKeys: String, CodingKey { case name, vehicles }

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
do {
let vehicle = try container.decode(Vehicle.self, forKey: .vehicles)
vehicles = [vehicle]
} catch DecodingError.typeMismatch {
vehicles = try container.decode([Vehicle].self, forKey: .vehicles)
}
}

关于 swift 可编码 : Continue parsing object after nested object error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52393915/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com