【问题标题】:Swift JSON parse with colon in JSON key name在 JSON 键名中使用冒号进行 Swift JSON 解析
【发布时间】:2021-04-15 14:39:48
【问题描述】:

你能在键名中有冒号的 JSON 上使用 Swift 的 JSONDecoder 吗?冒号在 Swift 中保留用于指示类型和协议等内容,因此当我尝试创建一个具有匹配键名的结构以与 JSONDecoder.decode 一起使用时,我会收到错误消息。示例 API: https://api.teleport.org/api/urban_areas/ 我想访问的城市列表在键中: “UA:项目” 但是 Swift 不允许使用此名称的属性来轻松进行 JSONDecoding。 我想坚持使用 JSONDecoder,因为它既简单又优雅。是否有一个简单的解决方法,或者我需要使用旧的解析技术。谢谢!

【问题讨论】:

标签: json swift decode


【解决方案1】:

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

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)
}

【讨论】:

    猜你喜欢
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2020-07-28
    相关资源
    最近更新 更多