【问题标题】:Swift JSONDecoder handling Dictionary of Array of DictionarySwift JSONDecoder 处理字典数组的字典
【发布时间】:2018-05-13 19:16:41
【问题描述】:

这是一个与 swift 上的 JSONDecoder 可编码功能相关的模型设计相关问题。

我有以下 JSON:

"author": {
    "name": "abc",
    "emailAddress": "abc@xyz.com",
    "id": 8665,
    "displayName": "A B C",
    "active": true,
    "slug": "abc",
    "type": "NORMAL",
    "links": {
        "self": [
                  {
                    "href": "some_href"
                  }
                ]
    }
 }

我正在尝试使用新的 swift 4 Codeable 功能对此进行解码。

因此我创建了如下结构:

struct Author: Codeable {
    let name: String,
    let emailAddress: String,
    let id: String,
    let displayName: String,
    let active: String,
    let type: String,
    let links: [String: [Link]] 
}

struct Link: Codeable {
    let href: String
} 

一旦我在这个 json 上运行 JSONDecoder().decode,我就会得到上述格式的模型对象。但是,Author 类中的 links 属性是作为字典获取的。现在要访问 self 字段的值,我需要大致执行以下操作:

let selfLink = author.links["self"]
let href = selfLink[0].href 

有没有更好的方法来为结构建模以避免这种情况?

【问题讨论】:

  • 谢谢@code-different 会试试这个。
  • 谢谢@jogendar-choudhary。将尝试这种方法。

标签: swift jsondecoder


【解决方案1】:

是的,您可以通过添加一个像这样的变量来做到这一点:

struct Author: Codable {
    let name: String
    let emailAddress: String
    let id: String
    let displayName: String
    let active: String
    let type: String
    let links: [String: [Link]]
    var linkArr: [Link]? {
        return links["self"]
    }
}

然后直接得到:

author.linkArr[0].href

【讨论】:

    【解决方案2】:

    如果你确定每个作者总是至少有 1 个href,你可以添加一个计算属性:

    struct Author: Codable {
        let name: String
        let emailAddress: String
        let id: String
        let displayName: String
        let active: String
        let type: String
    
        let links: [String: [Link]]     
        var href: String {
            return links["self"]!.first!.href
        }
    }
    

    您还可以通过声明private 来使links 无法从外部访问。

    【讨论】:

      【解决方案3】:

      在您的 JSON 中不太常见或至少命名不当的一件事是 links 属性实际上不是集合,而是集合 self 的包装器对象。这就是为什么我会忠于数据并将links 属性映射到名称linksWrapper(一个对象)和selflinks(一个集合)。

      struct Author: Codable {
          let name: String
          let emailAddress: String
          let id: Int
          let displayName: String
          let active: Bool
          let slug: String
          let type: String
          let linksWrapper: LinksWrapper
      
          enum CodingKeys: String, CodingKey {
              case name, emailAddress, id, displayName, active, slug, type
              case linksWrapper = "links"
          }
      }
      
      struct LinksWrapper: Codable {
          let links: [Link]
      
          enum CodingKeys: String, CodingKey {
              case links = "self"
          }
      }
      
      struct Link: Codable {
          let href: String
      }
      

      然后,您可以按照 JSON 模型建议的相同层次顺序访问链接,但名称更有意义:

      let myLinks = author.linksWrapper.links.first
      

      但为了您的方便,您可以将readonly links 属性添加到Author

      var links: [Link] {
          return linksWrapper.links
      }
      

      然后就可以直接访问链接了:

      let myLinks = author.links
      

      但是,如果您有机会在 JSON 结构本身中解决此问题,请改为这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-10
        • 1970-01-01
        • 2018-07-09
        • 1970-01-01
        • 2014-08-23
        • 2018-01-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多