-1

I've a problem with my functions for read a local JSON file. When I want to try to print anything in my parseJson(), nothing appear in my console.

Here's my JSON file :

{
  "questions":[
      {
          "question": "First Question ???",
          "response": "First Response",
      },
      {
          "question": "Second Question ???",
          "response": "Second Response",
      }
  ]
}  

Here's my questionsResult.swift

import Foundation

struct questionsResult: Decodable {
    var questions: [Questions]
}

struct Questions: Decodable {
    var question: String
    var response: String
}

And this is my function in my ViewController file :

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var questionsJson = [Questions]()

        func parseJSON(){
            if let url = Bundle.main.url(forResource: "test", withExtension: "json") {
                do {
                    let data = try Data(contentsOf: url)
                    let decoder = JSONDecoder()
                    let jsonData = try decoder.decode(questionsResult.self, from: data)
                    questionsJson.append(contentsOf: jsonData.questions)
                    print(url)

                } catch {
                    print("Json error \(error)")
                }
            }
        }
    }
}

Can you help me please ?

Galnash
  • 76
  • 8
  • I see some issues, `questionsJson` is declared immutable and your function takes a `Data` object as parameter but you are also reading a file from your main bundle. Also the error looks like a compilation error, is it? – Joakim Danielson Feb 23 '19 at 15:07

2 Answers2

1

Assuming you var declare your questionsJson array

var questionsJson = [Questions]()

this should work, notice I don't use any parameter but reads the file from the main bundle

if let url = Bundle.main.url(forResource: "test", withExtension: "json") {
    do {
        let data = try Data(contentsOf: url)
        let decoder = JSONDecoder()
        let jsonData = try decoder.decode(questionsResult.self, from: data)          
        questionsJson.append(contentsOf: jsonData.questions)
    } catch {
        print("Json error \(error)")
    }
}
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • 2
    `questionsResult.self` – matt Feb 23 '19 at 15:15
  • Thank you for your answers! I've updated the code and I've not any error. But when I want to print what is in my JSON, that doesn't show anything in the console. Do you know why ? – Galnash Feb 23 '19 at 15:33
  • @Galnash, no idea. I suggest you use the debugger to verify that the resource is found (or use a print statement for that as well) – Joakim Danielson Feb 23 '19 at 15:38
  • @JoakimDanielson A simple print() after the append should work isn't ? – Galnash Feb 23 '19 at 16:03
  • @Galnash Why not print the url as well `print(url)`? – Joakim Danielson Feb 23 '19 at 16:25
  • @JoakimDanielson I've try this but nothing appear in the console. I've try to print(jsonData) or (questionsJson) too but nothing append. My purpose is to looping to catch any element. – Galnash Feb 23 '19 at 16:32
  • If nothing happens then the file is probably empty or not found. – Joakim Danielson Feb 23 '19 at 16:47
  • @LeoDabus I've try with your code to replace `let jsonData = try decoder.decode(questionsResult.self, from: data)` with your code but still nothing... – Galnash Feb 23 '19 at 18:01
  • @Galnash still nothing it is way too vague. If you don't provide a minimum complete and verifiable example nobody will be able to help you. First you need to check if the Json text file has been added properly to your project bundle. If the file is there? Does data contents throws an error. If it does what does it print? – Leo Dabus Feb 23 '19 at 18:12
  • If you are adding multiple files (folder) to your project https://stackoverflow.com/questions/34548771/swift-how-do-i-get-the-file-path-inside-a-folder/34548888#34548888 – Leo Dabus Feb 23 '19 at 18:17
  • @LeoDabus I've my JSON file like in my first post. I've update the code with the code from Joakim. So now, I've the same code and no error. That's why I don't understand why I don't have anything in the console. If the file is not found, I should have an error message in my console right ? When I do a condition to check if the file is here, it does print the path so I guess it's okay. – Galnash Feb 23 '19 at 18:21
  • @Galnash pleas edit your question and post your code `let questionsJson = [Questions]()` is immutable. Your code should compile as it is posted. Where is your method declared? Where do you call it ? You didn't even show your viewDidLoad method. Post your view controller code (at least what is important and related to your question) ` – Leo Dabus Feb 23 '19 at 18:31
  • @LeoDabus I've edit my question and my ViewController in the original post – Galnash Feb 23 '19 at 18:44
  • @Galnash `var questionsJson = [Questions]()` should be declared as a property of your view controller. – Leo Dabus Feb 23 '19 at 18:45
  • 1
    move it out of your `viewDidLoad` method as well as your `func parseJSON()` method – Leo Dabus Feb 23 '19 at 18:46
  • The way you did `questionsJson` object and your parseJSON method only exits inside your viewDidLoad method – Leo Dabus Feb 23 '19 at 18:48
  • 1
    @LeoDabus Great! That's work now! Thank you for your answers and your time! – Galnash Feb 23 '19 at 18:55
0

The main issue in your code is were you added your code. var questionsJson = [Questions]() should be declared as a property of your view controller. Move it out of your viewDidLoad method as well as your func parseJSON() method. The way you did questionsJson object and your parseJSON method only exits inside your viewDidLoad method and they will go out of scope as soon as your method finishes.

struct Root: Decodable {
    let questions: [Question]
}

struct Question: Decodable {
    let question: String
    let response: String
}

class ViewController: UIViewController {

    var questions: [Question] = []

    func parseJSON() {
        do {
            let url = Bundle.main.url(forResource: "test", withExtension: "json")!
            let decoder = JSONDecoder()
            questions = try decoder.decode(Root.self, from: Data(contentsOf: url)).questions
            for question in questions {
                print(question)
            }
        } catch {
            print(error)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        parseJSON()
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571