使用Decodable和JSON

时间:2017-11-27 11:42:15

标签: ios json swift xcode decode

我有一个JSON文件,其格式如下:

[
  {
    "QID": "B002",
    "Stash": "Basic",
    "Category": "Geography",
    "Question": "What is the highest mountain on earth?",
    "Answer": "Mt Everest"
  },
  {
    "QID": "B003",
    "Stash": "Basic",
    "Category": "General",
    "Question": "What is the gestation period for a pregnant elephant?",
    "Answer": "2 years"
  }
]

我正在尝试创建一个结构,以便我可以将我的JSON文件中的所有问题加载到我的测验应用程序中。到目前为止,我从JSON和新的“可解码”事件中加入了苹果添加的东西,我的Swift代码如下所示(注意有一个失败的尝试被注释掉了):

var STASHES_SELECTED = ["BasicStash", "MediumStash", "HardStash"]

    struct TriviaQuestion: Decodable {
        let QID: String
        let Stash: String
        let Categoroy: String
        let Question: String
        let Answer: String
    }

    func loadQuestionStash()
    {
        /*
        for var i in STASHES_SELECTED
        {
         let url = Bundle.main.url(forResource: STASHES_SELECTED[i], withExtension: "JSON") //CANT GET THIS TO WORK!, SAYS CANNOT SUBSCRIPT TYPE [STRING] WITH INDEX TYPE 'STRING'
        }*/

        if let url = Bundle.main.url(forResource: "BasicStash", withExtension: "JSON")
        {
            let json = try? Data(contentsOf: url)

            let questions = try? JSONDecoder().decode(TriviaQuestion.self, from: json!)
            print (questions!) //FATAL ERROR, FOUND NIL

        }
    }

从代码注释中可以看出,目前给出了一个致命的错误“在展开时发现没有”。所以我假设前一行JSONDecoder()。非常失败。
我不确定我是否正确地执行此操作,因为这是我第一次使用JSON时,我刚刚在线阅读教程和帖子后非常棒。我真的很感激这里的一些帮助。此外,系统添加了TriviaQuestion之后的.self(我认为问题可能在那里的某处)

1 个答案:

答案 0 :(得分:2)

由于@Oxthor提到了输入错误,

我只想添加,始终使用quicktype.io来创建数据struct。你会避免拼写错误并节省你的时间:

// To parse the JSON, add this file to your project and do:
//
//   let triviaQuestion = Array.from(json: jsonString)!

import Foundation


struct TriviaQuestion: Codable {
    let answer: String
    let category: String
    let qID: String
    let question: String
    let stash: String
}

// MARK: Top-level extensions -

extension Array where Element == TriviaQuestion {
    static func from(json: String, using encoding: String.Encoding = .utf8) -> [PurpleTriviaQuestion]? {
        guard let data = json.data(using: encoding) else { return nil }
        return from(data: data)
    }

    static func from(data: Data) -> [TriviaQuestion]? {
        let decoder = JSONDecoder()
        return try? decoder.decode([TriviaQuestion].self, from: data)
    }

    static func from(url urlString: String) -> [TriviaQuestion]? {
        guard let url = URL(string: urlString) else { return nil }
        guard let data = try? Data(contentsOf: url) else { return nil }
        return from(data: data)
    }

    var jsonData: Data? {
        let encoder = JSONEncoder()
        return try? encoder.encode(self)
    }

    var jsonString: String? {
        guard let data = self.jsonData else { return nil }
        return String(data: data, encoding: .utf8)
    }
}

// MARK: Codable extensions -

extension TriviaQuestion {
    enum CodingKeys: String, CodingKey {
        case answer = "Answer"
        case category = "Category"
        case qID = "QID"
        case question = "Question"
        case stash = "Stash"
    }
}