一尘不染

快速可解码可选键

swift

(这是该问题的后续内容: 使用具有多个键的可解码协议。)

我有以下Swift代码:

let additionalInfo = try values.nestedContainer(keyedBy: UserInfoKeys.self, forKey: .age)
age = try additionalInfo.decodeIfPresent(Int.self, forKey: .realage)

我知道,如果我使用decodeIfPresent并且没有该属性,但如果它是一个可选变量,它仍然可以正确处理它。

例如,以下JSON可使用上面的代码来解析它。

{
    "firstname": "Test",
    "lastname": "User",
    "age": {"realage": 29}
}

以下JSON也适用。

{
    "firstname": "Test",
    "lastname": "User",
    "age": {"notrealage": 30}
}

但是以下操作无效。

{
    "firstname": "Test",
    "lastname": "User"
}

如何使所有3个示例正常工作?有什么类似decodeIfPresentnestedContainer


阅读 183

收藏
2020-07-07

共1个答案

一尘不染

您可以使用以下KeyedDecodingContainer功能:

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

返回一个Bool值,该值指示解码器是否包含与给定密钥关联的值。与给定键关联的值可以是适合于数据格式的空值。

例如, 请求相应的嵌套容器 之前 要检查"age"键是否存在: __

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
        }
    }
}
2020-07-07