使用 JSONDecoder 解包嵌套的 JSON 值

Posted

技术标签:

【中文标题】使用 JSONDecoder 解包嵌套的 JSON 值【英文标题】:Use JSONDecoder to unpack nested JSON values 【发布时间】:2017-12-28 20:44:39 【问题描述】:

如何从该 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
    

【问题讨论】:

【参考方案1】:

这与第二级的模式完全相同。您必须为任何字典创建一个单独的结构/类。结构的名称是任意的。父结构/类中的属性必须匹配字典键(本例中为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

【讨论】:

首先,非常感谢您这么快回答。但是你能帮我把这个“源”变量添加到表中吗,就像我添加了“名称”变量一样?这将使我的一天:) 使用这个:让课程=尝试 JSONDecoder().decode(JsonFromWeb.self, from: data) self.event = courses.data 有什么问题?您的代码应该可以工作。如果没有显示数据,则错误与自定义表格视图单元格有关 当我用您的代码替换我的部分代码时,会出现错误:(_BD6BE31D58877246570CAEB111C1E2ED 中的 CodingKeys).data,Foundation.(_12768CA107A31EF2DCE034FD75B541C9 中的_JSONKey)(stringValue:“索引 17”,intValue:可选( 17))], debugDescription: "No value associated with key cover (\"cover\").", underlyingError: nil)) 而且我不应该将它与变量一起使用? : cell.nameLabel.text = event[indexPath.row].name 如果cover 可以是nil 而不是使cover 可选:let cover: Cover? 是的,现在可以了。再次感谢您,您对我帮助很大! :)

以上是关于使用 JSONDecoder 解包嵌套的 JSON 值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 4 中使用 JSONDecoder 从嵌套 JSON 中获取数据?

Swift - 将类型动态传递给 JSONDecoder

iOS - JSONEncoder和JSONDecoder介绍

python3嵌套字典解包格式字符串

将 JSON 行解包到 pandas 数据框

如何使用 JSONDecoder 解码自定义 JSON 值