2017-10-14 24 views
1

(这是这个问题的后续:Using Decodable protocol with multiples keys雨燕可解码可选关键

我有以下的银行代码:

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个示例都可以工作? nestedContainer有没有类似于decodeIfPresent

回答

8

您可以使用以下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 
     } 
    } 
} 
0

您可以尝试将您的示例JSON粘贴到quicktype以查看它推断的类型?根据你的问题,我贴你的样品,并得到:

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

struct Age: Codable { 
    let realage: Int? 
} 

制作UserInfo.ageAge.realage自选作品,如果这是你要完成什么。

+1

我试图用1类/结构实现这一点。我有1个类/结构设计它的具体原因。有关详细信息,请参阅我的问题和答案[此处](https://stackoverflow.com/a/46737735/894067)。 –

+0

啊,我明白了 - 我必须同意那里的答案,这个答案提出了一个与JSON结构相对应的“原始”模型,您可以用您希望的特质行为映射到您的更高层模型!我认为这比实现定制解码器更容易维护和理解,但祝你好运! –

+0

就像我的数据在我的服务器文件中的结构一样,这使得使用自定义解码器更容易。而从我的理解和结构来看,以这种方式做起来要容易得多。也许有人能够给出符合我想要的答案。谢谢你的帮助。 –