我不希望我的代码在解码一个空字段时停止。

huangapple go评论62阅读模式
英文:

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)
    }
}

在这个代码中,我对 rentbuyflatrate 属性的解码进行了修改,使用 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) ?? []
    }
    
}

huangapple
  • 本文由 发表于 2023年7月12日 20:44:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76670706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定