ios - 使用 JSONDecoder 解压嵌套的 JSON 值

标签 ios json swift codable

如何从此 JSON 数据中获取三级值?

{
  "data": [
    {
      "id": "1669690663119337",
      "name": "Event1",
      "attending_count": 17,
      "cover": {
        "offset_x": 0,
        "offset_y": 50,
        "source": "https://imageurl",
        "id": "1769679396399074"
      }
    },
    {
      "id": "130418660933615",
      "name": "Event2",
      "attending_count": 923,
      "cover": {
        "offset_x": 0,
        "offset_y": 50,
        "source": "https://imageurl",
        "id": "10156609677937586"
      }
    },
    {
      "id": "1883372648594017",
      "name": "Event3",
      "attending_count": 1695,
      "cover": {
        "offset_x": 0,
        "offset_y": 50,
        "source": "imageurl",
        "id": "10156575272607586"
      }
    }

对于二级值(id、name、attending_count),我使用这些代码行:

struct JsonFromWeb: Codable {
    let data: [Course]
}

struct Course: Codable {
    let id: String?
    let name: String?
    let attending_count: Int?
}


class JsonViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var eventTable: UITableView!

    var event = [Course]()

    override func viewDidLoad() {
        super.viewDidLoad()
            let jsonUrlString = "https://www.jsonurl.url/"
            guard let url = URL(string: jsonUrlString) else { return }
            print(jsonUrlString)
            URLSession.shared.dataTask(with: url) { (data, response, err) in
                guard let data = data else { return }
                do {
                    let courses = try JSONDecoder().decode(JsonFromWeb.self, from: data)
                    self.event = courses.data
                    DispatchQueue.main.async {
                        self.eventTable.reloadData()
                    }
                } catch let jsonErr {
                    print("Error jsonErr", jsonErr)
                }
                }.resume()
        }

    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return event.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell") as? UserEventsTableViewCell else { return UITableViewCell() }
        cell.nameLabel.text = event[indexPath.row].name
        return cell
    }
}

最佳答案

这与第二层的模式完全相同。您必须为任何字典创建一个单独的结构/类。结构的名称是任意的。父结构/类中的属性必须匹配字典键(在本例中为 cover)

struct JsonFromWeb: Codable {
    let data: [Course]
}

struct Course: Codable {

    private enum CodingKeys : String, CodingKey {
        case attendingCount = "attending_count"
        case id, name, cover
    }
    let id: String
    let name: String
    let attendingCount: Int
    let cover: Cover
}    

struct Cover : Codable {

    private enum CodingKeys : String, CodingKey {
        case offsetX = "offset_x"
        case offsetY = "offset_y"
        case source, id
    }
    let offsetX: Int
    let offsetY: Int
    let source: String
    let id: String
}

注意:

永远不要使用这种语法

guard let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell") as? UserEventsTableViewCell else { 
    return UITableViewCell() 
}

这是为数不多的建议强制展开以发现设计错误的案例之一。如果一切都正确连接,代码一定不会崩溃。并使用始终返回有效单元格的 dequeue API:

let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! UserEventsTableViewCell

关于ios - 使用 JSONDecoder 解压嵌套的 JSON 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48014143/

相关文章:

ios - 如何在 iOS 中播放视频 PHAsset?

ios - 被 iTunes Connect 拒绝,原因为 "Your iTunes Connect settings indicate that your app serves third-party advertisements. "

swift - Swift 中的泛型和协议(protocol) : Why does my $0 have no expectation member?

ios - 解析: PFUser.enableAutomaticUser不创建用户

swift - 我正在从 Swift Playground 保存一个文本文件。但无法在我的 Mac 中找到该文件

ios - 使用分段控件切换tableView

ios - 如何在 iOS 中裁剪到信箱

php - 在 Swift 中将 JSON 数据解析为 UIPickerView

java - 如果 JSON 数组为空,则更改文本

javascript - 使用 Angular 2 序列化和反序列化 JSON