【问题标题】:Swift Json how to decode with no top level key and autogenerated keysSwift Json 如何在没有顶级密钥和自动生成的密钥的情况下进行解码
【发布时间】:2021-05-13 02:52:17
【问题描述】:

这个对我没有帮助:Swift 4 parsing json numeric keys with 1+n amount

情况不同。

我有这个 JSON(简化了一点):

{
        "1": {
            "name": "Tea room",
            "description": "A room for tea"
        },
        "2": {
            "name": "Playground",
            "description": "Here you can play all day long"
        },
        "3": {
            "name": "Kitchen",
            "description": "Hungry persons can go here"
        }
    }

我的问题是如何解码。我正在使用 Swift 版本 5。我正在尝试使用 JSONDecoder().decode();

键“1”、“2”和“3”实际上是 Id,由 API 生成。我不知道我会收到多少个房间。而且我不知道他们会有什么钥匙,但我需要知道钥匙(Id)才能走得更远。

我正在做这样的事情:

struct Rooms: Decodable {
  let id: Int; //THIS ONE IS MY PROBLEM
  let rooms: [Room]?;
}

struct Room: Decodable {
    let name: String?;
    let description: String?;
        
    private enum CodingKeys: String, CodingKey {
        case name, description;
    }
}

//Here trying to decode the JSON I got back.
JSONDecoder().decode([Group].self, from: jsonResult);

这让我头疼:)

谁能帮助我正确的方向?

【问题讨论】:

  • 您需要使用自定义解码。如果您有可变键,则不能依赖自动解码。

标签: json swift decode


【解决方案1】:

您可以将其解码为字典:[String: Room]:

JSONDecoder().decode([String: Room].self, from: jsonResult);

【讨论】:

    【解决方案2】:

    鉴于此模型(如果属性名称与您的 JSON 键名称相同,则不需要CodingKeys):

    struct Room: Decodable {
        let name: String?
        let description: String?
    }
    

    您可以将此 JSON 解码为[String: Room] 类型:

    let decoder = JSONDecoder()
    
    do {
        let decoded = try decoder.decode([String: Room].self, from: jsonResult)
        print(decoded)
    } catch {
        print(error)
    }
    

    【讨论】:

      【解决方案3】:

      既然你需要 id 它应该是 Room 的一个属性

      struct Room: Decodable {
          var id: Int?
          let name: String
          let description: String
      }
      

      这样我们可以将 json 解码为 [String: Room] 的字典,并使用 map 将正确的 id 分配给每个房间

      do {
          let dictionary = try JSONDecoder().decode([String: Room].self, from: data)
          let rooms = dictionary.map { tuple -> Room in
              var room = tuple.value
              room.id = Int(tuple.key)
              return room
          }
          print(rooms)
      } catch {
          print(error)
      }
      

      如果您不想将id 设为可选,您可以将其解码为字典字典并在映射时创建 Room 对象

      do {
          let dictionary = try JSONDecoder().decode([String: [String: String]].self, from: data)
          let rooms = dictionary.compactMap { tuple -> Room? in
              guard let id = Int(tuple.key), let name = tuple.value["name"], let description = tuple.value["description"] else {
                  return nil
              }
              return Room(id: id, name: name, description: description)
          }
          print(rooms)
      } catch {
          print(error)
      }
      

      【讨论】:

      • 感谢您的帮助。实际上,我确实在 Udemy 上找到了速成课程。并查看每一秒。现在我开始跑步了。
      猜你喜欢
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      相关资源
      最近更新 更多