微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 JSON 键名中的冒号进行 Swift JSON 解析

如何解决使用 JSON 键名中的冒号进行 Swift JSON 解析

您可以在键名中有冒号的 JSON 上使用 Swift 的 JSONDecoder 吗?冒号在 Swift 中被保留用于指示类型和协议之类的事情,所以当我尝试创建一个具有匹配键名的结构以与 JSONDecoder.decode 一起使用时,我会得到一个错误。示例 API: https://api.teleport.org/api/urban_areas/ 我想访问的城市列表是关键: “ua:项目” 但是 Swift 不允许使用此名称属性来简化 JSONDecoding。 我想坚持使用 JSONDecoder,因为它非常简单和优雅。是否有一个简单的解决方法,或者我是否需要依靠旧的解析技术。谢谢!

解决方法

这是您正在调用的 API 的 JSON 响应的简化版本。我只是限制了每个数组中的项目数量,因为一遍又一遍地列出类似项目变得重复。

let data = """
{
  "_links": {
    "curies": [
      {
        "href": "https://developers.teleport.org/api/resources/Location/#!/relations/{rel}/","name": "location","templated": true
      }
    ],"self": {
      "href": "https://api.teleport.org/api/urban_areas/"
    },"ua:item": [
      {
        "href": "https://api.teleport.org/api/urban_areas/slug:aarhus/","name": "Aarhus"
      },{
        "href": "https://api.teleport.org/api/urban_areas/slug:adelaide/","name": "Adelaide"
      }
    ]
  },"count": 266
}
""".data(using: .utf8)!

JSON 中有几个问题,但我们可以使用 CodingKeys 轻松修复它们。注意CodingKey的大小写值必须与变量名匹配,编码键的字符串值必须与JSON中的值匹配,如果值相同我们可以跳过写字符串值。

JSON 存在三个问题

  • _links
  • self
  • ua:item

按照惯例,Swift 中的变量通常不以下划线开头,因此删除它是有意义的。我们可以使用第一组 CodingKeys 做到这一点。

self 是 Swift 中的保留字,所以我们应该用更合适的词替换它,在这种情况下我选择了 link

正如您已经注意到的,变量名称中不能有冒号。我们可以用更合适的东西替换它,在本例中为 uaItem

这给出了以下结构。如果您将上述数据变量带入游乐场,它应该都能很好地解码。

struct Response: Decodable {
    let links: Links
    let count: Int

    // These are the coding keys for Response
    enum CodingKeys: String,CodingKey {
        case links = "_links"
        case count
    }

    struct Links: Decodable {
        let curies: [Curie]
        let link: HREF
        let uaItem: [UAItem]

        // These are the coding keys for Links
        enum CodingKeys: String,CodingKey {
            case curies
            case link = "self"
            case uaItem = "ua:item"
        }
    }

    struct Curie: Decodable {
        let href: String
        let name: String
        let templated: Bool
    }

    struct HREF: Decodable {
        let href: String
    }

    struct UAItem: Decodable {
        let href: String
        let name: String
    }
}


do {
    let result = try JSONDecoder().decode(Response.self,from: data)
    print(result)
} catch {
    print(error)
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。