英文:
II don't want my code to stop when decoding a field I'm decoding is empty
问题
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String?
let rent: [WatchProviderDetails]?
let buy: [WatchProviderDetails]?
let flatrate: [WatchProviderDetails]?
enum CodingKeys: String, CodingKey {
case link
case rent
case buy
case flatrate
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
link = try container.decodeIfPresent(String.self, forKey: .link)
rent = try? container.decodeIfPresent([WatchProviderDetails].self, forKey: .rent)
buy = try? container.decodeIfPresent([WatchProviderDetails].self, forKey: .buy)
flatrate = try? container.decodeIfPresent([WatchProviderDetails].self, forKey: .flatrate)
}
}
在这个代码中,我对 rent
、buy
和 flatrate
属性的解码进行了修改,使用 try?
来尝试解码可选的数组。这样,如果这些字段为空或不存在,它们将被设置为 nil
,而不会引发错误。这应该解决你遇到的问题,让你能够更好地处理空字段。
英文:
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String?
let rent: [WatchProviderDetails]?
let buy: [WatchProviderDetails]?
let flatrate: [WatchProviderDetails]?
enum CodingKeys: String, CodingKey {
case link
case rent
case buy
case flatrate
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
link = try container.decodeIfPresent(String.self, forKey: .link)
rent = try container.decode([WatchProviderDetails].self, forKey: .rent)
buy = try container.decode([WatchProviderDetails].self, forKey: .buy)
flatrate = try container.decode([WatchProviderDetails].self, forKey: .buy)
}
}
So I'm getting data from api and decoding it into this struct. Thing is sometimes rent would be empty, other times, flatrate would be empty, etc.. Problem is though, everytime any field is empty
> sink error: keyNotFound(CodingKeys(stringValue: "rent", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), CodingKeys(stringValue: "US", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: "rent", intValue: nil) ("rent").", underlyingError: nil))
Any help how can I overcome that error, or better ignore it when it isn't there?
答案1
得分: 1
A simple solution is to delete init(from decoder:)
如果一个结构体成员被声明为可选的,如果对应的键缺失,它将保持为nil
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String?
let rent: [WatchProviderDetails]?
let buy: [WatchProviderDetails]?
let flatrate: [WatchProviderDetails]?
enum CodingKeys: String, CodingKey {
case link, rent, buy, flatrate
}
}
如果结构体成员是非可选的,并且您希望在键缺失时分配默认值,decodeIfPresent
就会有用
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String
let rent: [WatchProviderDetails]
let buy: [WatchProviderDetails]
let flatrate: [WatchProviderDetails]
enum CodingKeys: String, CodingKey {
case link, rent, buy, flatrate
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
link = try container.decodeIfPresent(String.self, forKey: .link) ?? ""
rent = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .rent) ?? []
buy = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .buy) ?? []
flatrate = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .flatrate) ?? []
}
}
英文:
A simple solution is to delete init(from decoder:)
If a struct member is declared as optional it remains nil
if the corresponding key is missing
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String?
let rent: [WatchProviderDetails]?
let buy: [WatchProviderDetails]?
let flatrate: [WatchProviderDetails]?
enum CodingKeys: String, CodingKey {
case link, rent, buy, flatrate
}
}
decodeIfPresent
is useful if the struct member is non-optional and you want to assign a default value if the key is missing for example
struct WatchProvider: Identifiable, Decodable {
let id = UUID()
let link: String
let rent: [WatchProviderDetails]
let buy: [WatchProviderDetails]
let flatrate: [WatchProviderDetails]
enum CodingKeys: String, CodingKey {
case link, rent, buy, flatrate
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
link = try container.decodeIfPresent(String.self, forKey: .link) ?? ""
rent = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .rent) ?? []
buy = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .buy) ?? []
flatrate = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .flatrate) ?? []
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论