Swift Decodable Optional Key

前端 未结 3 2125

(This is a follow-up from this question: Using Decodable protocol with multiples keys.)

I have the following Swift code:

let additionalInfo          


        
相关标签:
3条回答
  • 2020-12-09 11:11

    You can use the following KeyedDecodingContainer function:

    func contains(_ key: KeyedDecodingContainer.Key) -> Bool
    

    Returns a Bool value indicating whether the decoder contains a value associated with the given key. The value associated with the given key may be a null value as appropriate for the data format.

    For instance, to check if the "age" key exists before requesting the corresponding nested container:

    struct Person: Decodable {
        let firstName, lastName: String
        let age: Int?
    
        enum CodingKeys: String, CodingKey {
            case firstName = "firstname"
            case lastName = "lastname"
            case age
        }
    
        enum AgeKeys: String, CodingKey {
            case realAge = "realage"
            case fakeAge = "fakeage"
        }
    
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            self.firstName = try values.decode(String.self, forKey: .firstName)
            self.lastName = try values.decode(String.self, forKey: .lastName)
    
            if values.contains(.age) {
                let age = try values.nestedContainer(keyedBy: AgeKeys.self, forKey: .age)
                self.age = try age.decodeIfPresent(Int.self, forKey: .realAge)
            } else {
                self.age = nil
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-09 11:13

    I had this issue and I found this solution, just in case is helpful to somebody else:

    let ageContainer = try? values.nestedContainer(keyedBy: AgeKeys.self, forKey: .age)
    self.age = try ageContainer?.decodeIfPresent(Int.self, forKey: .realAge)
    

    If you have an optional container, using try? values.nestedContainer(keyedBy:forKey) you don't need to check if the container exist using contains(.

    0 讨论(0)
  • 2020-12-09 11:22

    Can you try pasting your sample JSON into quicktype to see what types it infers? Based on your question, I pasted your samples and got:

    struct UserInfo: Codable {
        let firstname: String
        let age: Age?
        let lastname: String
    }
    
    struct Age: Codable {
        let realage: Int?
    }
    

    Making UserInfo.age and Age.realage optionals works, if that's what you're trying to accomplish.

    0 讨论(0)
提交回复
热议问题