使用 Codable 解析多级 JSON

Posted

技术标签:

【中文标题】使用 Codable 解析多级 JSON【英文标题】:Parsing multi-level JSON with Codable 【发布时间】:2020-02-27 15:21:25 【问题描述】:

我正在尝试将 JSON 解析为 tableView : https://www.pathofexile.com/api/trade/data/items

我成功解析了第一个数组,但是我无法解析关键的“条目”...

这是我的代码,我定义的数据结构:


import UIKit

struct ItemCategories: Codable 
    var result: [ItemCategory]


struct ItemCategory: Codable 
    var label: String
    var entries: [Item]


struct Item: Codable 
    // empty struct


class ViewController: UITableViewController 

    let urlString = "https://www.pathofexile.com/api/trade/data/items"
    var categories = [ItemCategory]()

    override func viewDidLoad() 
        super.viewDidLoad()
        title = "Path of Data"
        navigationController?.navigationBar.prefersLargeTitles = true
        parse()
    

    func parse() 
        guard let url = URL(string: urlString) else  return 
        guard let data = try? Data(contentsOf: url) else  return 
        let decoder = JSONDecoder()
        guard let jsonItemCategories = try? decoder.decode(ItemCategories.self, from: data) else  return 
        categories = jsonItemCategories.result
        tableView.reloadData()
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return categories.count
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        var categoryName = categories[indexPath.row].label
        if categoryName == ""  categoryName = "Unknown" 
        cell.textLabel?.text = categoryName
        cell.textLabel?.textColor = .systemOrange
        let numberOfItemsInCategory = String(categories[indexPath.row].entries.count)
        cell.detailTextLabel?.text = numberOfItemsInCategory + " items"
        return cell
    


struct Item 是空的,因为当我尝试在 JSON 中添加与键对应的变量时,整个解析失败(tableView 什么都不显示)。

当struct Item为空时,则解析成功,tableView能够显示不同的类别。它甚至显示每个“条目”的项目数,这要归功于:

let numberOfItemsInCategory = String(categories[indexPath.row].entries.count)
cell.detailTextLabel?.text = numberOfItemsInCategory + " items"

有人可以解释为什么吗?理想情况下,我想在点击行时显示“条目”的内容,但我暂时不知道如何。

谢谢你的帮助:)

screenshot

【问题讨论】:

try? => 否! 改为:do ... try ... catch print("Error: \(error)"。它应该告诉你为什么之前的解码尝试失败了。我们无法猜测出了什么问题。所以使用do/catch,告诉我们到底出了什么问题。 不相关但是:避免使用Data(contentsOf:),它会阻塞当前线程,而是使用URLSession 在我的机器上解析没有问题。 例如,"Ivory Watchstone" 的情况是“不完整的”,我猜是可选值(只有“名称”和“类型”属性)。这是最后一个 @Larme 你的意思是typetext。缺少的是name 【参考方案1】:

@Laurent Delorme 你的结构Item 应该如下所示,试试这个,

    struct Item: Codable 

    let name: String?

    let type: String?

    let text: String?

    let flags: FlagsRepresentation?

    enum CodingKeys: String, CodingKey 

        case name
        case type
        case text
        case flags
    


struct FlagsRepresentation: Codable 

    let unique: Bool?

    enum CodingKeys: String, CodingKey 

        case unique
    

【讨论】:

在这种情况下,您实际上可以摆脱 CodingKeys。

以上是关于使用 Codable 解析多级 JSON的主要内容,如果未能解决你的问题,请参考以下文章

使用 Codable 解析嵌套 JSON 数据问题

使用 Codable 解析嵌套的 JSON 数据

swift 中使用Codable进行数据解析

使用 URLSession 和 Codable 解析 JSON 数据

使用 Codable 解析 JSON 数据

如何使用 Codable 和 Swift 解析这个嵌套的 JSON?