Swift 将 JSON 解析为 Table 视图不起作用

Swift parsing JSON into Table View doesnt work

您好,我无法将 Json 数据读入 TableView。 任何人都可以帮助我,这是我第一次使用它。 我知道我做错了什么,但我无法为我的 JSON 文件找到解决方案,因为在互联网上他们使用简单的..

这是我的 JSON:

{
    "data":[
        {
            "title": "Brot",
            "desc":[
                {
                    "Name": "Roggenschrot- und Roggenvollkornbrot",
                    "Menge": "Gramm",
                    "Kalorie": "2",
                    "Energiedichte": "Gelb"
                },
                {
                    "Name": "Weizenschrot- und Weizenvollkornbrot",
                    "Menge": "Gramm",
                    "Kalorie": "2",
                    "Energiedichte": "Gelb"
                },
                {
                    "Name": "Weizenschrot- und Weizenvollkornbrot",
                    "Menge": "Gramm",
                    "Kalorie": "2",
                    "Energiedichte": "Gelb"
                },
            ]
        }
    ]
}

这是我的 tableView

import UIKit

class EseenTagebuchTableViewController: UITableViewController {
    
    var result: Result?
    var resultItem: ResultItem?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        parseJSON()

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return result?.data.count ?? 0
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return result?.data[section].title
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        if let result = result {
            return result.data.count
        }
        return 0
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let text = resultItem?.desc?[indexPath.section].Name?[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = text
        return cell
    }
    

    private func parseJSON() {
        guard let path = Bundle.main.path(forResource: "Ernahrungstagebuch", ofType: "json") else {
            return
        }
        let url = URL(fileURLWithPath: path)
        
       
        
        do {
            let jsonData = try Data(contentsOf: url)
            result = try JSONDecoder().decode(Result.self, from: jsonData)
            return
        }
        catch {
            print("Error: \(error)")
        }
    }

}

这是我的模型 1 和模型 2 之后的模型

import Foundation

struct Result: Codable {
    let data: [ResultItem]
   
}

struct ResultItem: Codable {
    let title: String
    let desc: [descItems]?
}

模型 2

import Foundation

struct descItems: Codable {
    let Name: String?
    let Menge: String?
    let Kalorie: Int?
    let Energiedichte: String?
}

我做错了什么?

你也可以使用json解析下面的代码:

func parseJSON() {
let path =  Bundle.main.path(forResource: "Ernahrungstagebuch", ofType: "json")
let jsonData = try? NSData(contentsOfFile: path!, options: NSData.ReadingOptions.mappedIfSafe)
let jsonResult: NSDictionary = try! (JSONSerialization.jsonObject(with: jsonData! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary)!

if let data = jsonResult["data"] as? [[String:Any]] {
    self.arrPlan = data.map{Day(JSON: [=10=])!}
    //            print(arrPlan)
    
}

}

尝试使用此代码获取数据数组对象并在重新加载 tableview 数据后。

您可以使用这个扩展解析json

import Foundation

extension Bundle {
    func decode<T: Decodable>(_ type: T.Type, from file: String, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T {
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Failed to locate \(file) in bundle.")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file) from bundle.")
        }

        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = dateDecodingStrategy
        decoder.keyDecodingStrategy = keyDecodingStrategy

        do {
            return try decoder.decode(T.self, from: data)
        } catch DecodingError.keyNotFound(let key, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing key '\(key.stringValue)' not found – \(context.debugDescription)")
        } catch DecodingError.typeMismatch(_, let context) {
            fatalError("Failed to decode \(file) from bundle due to type mismatch – \(context.debugDescription)")
        } catch DecodingError.valueNotFound(let type, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing \(type) value – \(context.debugDescription)")
        } catch DecodingError.dataCorrupted(_) {
            fatalError("Failed to decode \(file) from bundle because it appears to be invalid JSON")
        } catch {
            fatalError("Failed to decode \(file) from bundle: \(error.localizedDescription)")
        }
    }
}

并像这样使用它:

let incomingData = Bundle.main.decode([Your_Model].self, from: "Your_Json_File_name.json")

首先你的json文件中的数据不正确,后面多了一个“,”逗号 最后一个 "Energiedichte": "Gelb" ,将其从您的文件中删除。

其次你的模型不正确,你应该有:

struct Result: Codable {
    let data: [ResultItem]
}

struct ResultItem: Codable {
    let title: String
    let desc: [DescItems]?
}

struct DescItems: Codable {
    let Name: String?
    let Menge: String?
    let Kalorie: String?  // <-- here not Int?
    let Energiedichte: String?
}

使用您的代码parseJSON()我能够无误地解析数据。

EDIT-1:如果您真的希望 kalories 成为 Int,请尝试:

struct DescItems: Codable {
    let name: String?
    let menge: String?
    let kalorie: Int?  // <-- here
    let energiedichte: String?
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        menge = try container.decode(String.self, forKey: .menge)
        energiedichte = try container.decode(String.self, forKey: .energiedichte)
        let calorie = try container.decode(String.self, forKey: .kalorie)  // <-- here
        kalorie = Int(calorie) // <-- here
    }
    
    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case menge = "Menge"
        case kalorie = "Kalorie"
        case energiedichte = "Energiedichte"
    }
}

根据惯例注意大小写的变化。