【问题标题】:Parsing Array of dictionaries in Swift using Codable使用 Codable 在 Swift 中解析字典数组
【发布时间】:2020-01-22 03:17:53
【问题描述】:

我有一个来自 API 的 JSON 响应,但我不知道如何使用 Swift Codable 将其转换为用户对象(单个用户)。这是 JSON(为了便于阅读,删除了一些元素):

{
  "user": [
    {
      "key": "id",
      "value": "093"
    },
    {
      "key": "name",
      "value": "DEV"
    },
    {
      "key": "city",
      "value": "LG"
    },
    {
      "key": "country",
      "value": "IN"
    },
    {
      "key": "group",
      "value": "OPRR"
    }
  ]
}

【问题讨论】:

  • 在这种情况下你不太可能使用Codable 协议。这是一种非常奇怪的 API 数据组织方式。您需要从数据对象中手动解析出来。
  • @inokey,同意你的 API 响应,我发现很难解析它。任何其他如何映射它的建议,真的会有所帮助:(
  • 如果您知道如何组织 API,您可以要求反手开发人员返回一个对象。如果情况不是很好,那么在引入 Codable 协议之前,您需要采用经典的方式来解析 json 对象。这包括将Data 序列化为Dictionary 并通过每个键手动解析内容。尽管如果属性列表可能发生变化并遗漏某些字段,那么无论如何您都很难将内容组合到一个实体 User 对象中。
  • 哦,看来我需要采用经典的方式,没有其他选择,但似乎不是有效的方式来映射键和值。谢谢你的建议。如果你把它作为答案,我愿意接受你的建议。
  • 好的,我发布了这个作为答案。

标签: json swift codable


【解决方案1】:

如果您愿意,可以分两步完成。首先为接收到的json声明一个struct

struct KeyValue: Decodable {
    let key: String
    let value: String
}

然后解码 json 并使用键/值对将结果映射到字典中。

do {
    let result = try JSONDecoder().decode([String: [KeyValue]].self, from: data)

    if let array = result["user"] {
        let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}

然后将此字典编码为 json 并使用 User 的结构再次返回

struct User: Decodable {
    let id: String
    let name: String
    let group: String
    let city: String
    let country: String
}

let userData = try JSONEncoder().encode(dict)
let user = try JSONDecoder().decode(User.self, from: userData)

整个代码块就变成了

do {
    let decoder = JSONDecoder()
    let result = try decoder.decode([String: [KeyValue]].self, from: data)

    if let array = result["user"] {
        let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}
        let userData = try JSONEncoder().encode(dict)
        let user = try decoder.decode(User.self, from: userData)
        //...
    }
} catch {
    print(error)
}

有点麻烦,但不需要手动匹配键/属性。

【讨论】:

    【解决方案2】:

    创建一个包含 2 个变量 key 和 value 的结构

    public struct UserModel: Codable {
        public struct User: Codable {
            public let key: String
            public let value: String
        }
        public let user: [User]
    }
    

    之后使用 JSONDecoder 解码您的字符串。

    func decode(payload: String) {
        do {
            let template = try JSONDecoder().decode(UserModel.self, from: payload.data(using: .utf8)!)
        } catch {
           print(error)
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试这样的结构

      struct Model: Codable {
          struct User: Codable {
              let key: String
              let value: String
          }
          let singleuser: [User]
      }
      

      【讨论】:

      • 我认为这并不能真正解决问题,尽管这正是通过 Codable 解析这个 json 的方法。
      猜你喜欢
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多