首页 > 解决方案 > 使用可编码解析 JSON 时出错

问题描述

我正在尝试使用 Swift 中新的(ish)可编码功能从 JSON 文件中传递一些数据。我之前使用过以下语法没有问题。但是,我相信我可能设置了错误,因为我似乎无法理解为什么当 JSON 格式已被 JSON 解析器批准时,我一直收到以下消息。

错误信息:

错误:dataCorrupted(Swift.DecodingError.Context(codingPath:[],debugDescription:“给定的数据不是有效的JSON。”,基础错误:可选(错误域=NSCocoaErrorDomain Code=3840“JSON文本没有以数组或对象开头,并且允许未设置片段的选项。" UserInfo={NSDebugDescription=JSON 文本未以数组或对象开头,并且允许未设置片段的选项。})))

我的 QuestionFactory 文件中的代码...

class QuestionFactory {

func parseJSON(filename fileName: String) -> Quiz? {
    if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
        print(url)
        do {
            let data = try Data(contentsOf: url)
            let decoder = JSONDecoder()
            print("data received is \(data.count) bytes:\n\(data)")
            print(data)
            print(data as NSData)
            let jsonData = try decoder.decode(Quiz.self, from: data)

            print(jsonData)
        } catch {
            print("error:\(error)")
        }
    }
    return nil
}
}

我最初的 ViewController 中的代码:

class LaunchScreen: UIViewController {


  private var quiz: Quiz?
  private let jsonFileName = "QuizData"


 func viewDidLoad() {
    super.viewDidLoad()
    createQuiz()
 }


   private func createQuiz() {
    let questionFactory = QuestionFactory()
    guard let parsedQuiz = questionFactory.parseJSON(filename: jsonFileName) else {
        print("Error creating quiz")
        return
    }
    quiz = parsedQuiz
}

func movesToMainMenuScreen() {
    let transition = CATransition()
    transition.duration = 1.5
    transition.type = kCATransitionFade
    self.navigationController?.view.layer.add(transition, forKey:nil)
    let mainMenuVC: UIViewController = MainMenuViewController(quiz: quiz!) >> I am receiving an error here as well, perhaps due to my mainMenuVC's required init?
    navigationController?.pushViewController(mainMenuVC, animated: false)
}

在我的 mainMenuViewController 中:

class mainMenuViewController: UIViewController {

private var quiz: Quiz! {
    didSet {
    tableViewAdapter = AnswerTableViewAdapter(answers: quiz.questions[0].answers) >> Although, it is not obviously reaching this far to read through the JSON.
}

required init(quiz: Quiz) {
    super.init(nibName: nil, bundle: nil)
    defer {
        self.quiz = quiz
    }
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

JSON看起来像这样......

{
"questions":[
             {
             "text": "1. Where will the 2022 World cup be held?",
             "answers": [
                         {
                         "text": "Qatar",
                         "isCorrect": true,
                         "answerType": "2"
                         },
                         {
                         "text": "دولة قطر",
                         "isCorrect": true,
                         "answerType": "1"
                         },
                         {
                         "text": "Jamaica",
                         "isCorrect": false,
                         "answerType": "0"
                         },
                         {
                         "image":"qatarFlag",
                         "isCorrect": true,
                         "answerType": "3"
                         }
                         ]
             }]
}

模型文件....

测验.swift

import Foundation

struct Quiz: Decodable {
  var questions: [Question]
}

问题.swift

import Foundation

struct Question: Decodable {
  var text: String
  var answers: [Answer]
}

答案.swift

import Foundation

struct Answer: Decodable {
  var text: String
  var image: String
  var isCorrect: Bool
  var answerType: String
}

标签: jsonswiftjsondecoder

解决方案


有额外的

    ]
}

在最后两行添加删除这两个右括号并尝试解析 JSON。

并将模型的属性设为可选以避免可为空的崩溃。

模型文件....

测验.swift

import Foundation
struct Quiz: Decodable {
    var questions: [Question]?
}

问题.swift

import Foundation
struct Question: Decodable {
  var text: String?
  var answers: [Answer]?
}

答案.swift

import Foundation
struct Answer: Decodable {
  var text: String?
  var image: String?
  var isCorrect: Bool?
  var answerType: String?
}

推荐阅读