0

I have been struggling all week. I am new to programming. I cannot turn a simple JSON file into a dictionary in Xcode. There is little simplified documentation online using the new method of Codable. So I am using a walkthrough, which has the following code.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let path = Bundle.main.path(forResource: "menu", ofType: "json") else { return }
        let url = URL(fileURLWithPath: path)

        do {

            let data = try Data(contentsOf: url)
            let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
            //print(json)

            guard let array = json as? [Any] else { return }
            for user in array {
                guard let userDict = user as? [String: Any] else { return }
                guard let drinks = userDict["drinks"] as? String else { print("not a String"); return }
                guard let junkFood = userDict["junk-food"] as? String else { return }

                print(drinks)
                print(junkFood)
                print(" ")
            }
        }
        catch {
            print(error)
        }

    }

}

The below code is what my JSON looks like.

{"menu": {
  "drinks": [
    {"coke": "20"},
    {"pepsi": "20"},
    {"water": "20"}
  ],
  "junk-food": [
    {"hamburger": "40"},
    {"fries": "20"},
    {"pizza": "20"}
  ]
}}

Can anyone please walk me through, or show me some simplified documentation as to how I can turn the JSON into a dictionary that I can later map the data from? I am using Xcode and trying to work out Swift 4.

Thanks in advance for your patience.

2
  • How far does the code you posted get? And please update your question. Your title says you want an array. The end of your question says you want a dictionary. Your code indicates your JSON file is an array of dictionary. Commented Aug 16, 2017 at 22:02
  • My apologies, I meant Dictionary. It does completely print. But I can completely comment out all the code within the second guard let. So I'm guessing it is not reading that part of the code. Thanks for your swift reply Commented Aug 16, 2017 at 22:08

1 Answer 1

1

My guess is that your json is actually a Dictionary not an Array. So guard let array = json as? [Any] else { return } is falling through because the json is [String: Any]. You can get to the array with the "menu" key.

Here's an updated version of your code:

 do {
        let data = try Data(contentsOf: url)
        let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
        //print(json)

        guard let menuDict = json as? [String: Any] else { return }

        guard let drinks = menuDict["drinks"] as? [[String: Any]] else { 
            print("not an array of dictionaries") 
            return 
        }

        guard let junkFood = menuDict["junk-food"] as? [[String: Any]] else { 
            print("not an array of dictionaries") 
            return 
        }
        print(drinks)
        print(junkFood)
        print(" ")
    }

Try that, let me know if it works. This is just the do block by the way.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks again for your reply, the code certainly goes further, however, now the two print lines under the guard statements are coming up with the following error.. Cannot invoke 'print' with an argument list of type '(String, () -> ()) Specifically pointing towards the beginning of the return commands.
Ok @erdos, I put in a couple of ; to separate the return statements from the print statements in the guard lets. This is now printing to the screen as "not an array of dictionaries". Thanks for your help thus far, I will continue to plug away and see if I can get it working.
do you think it would have an effect on the data not being able to be transferred into a dictionary because when the data from the JSON is parsed, the output replaces the : with = (The colons with equals). Here is the JSON data looks like when printed to the console.... '["menu": { drinks = ( { coke = 20; }, { pepsi = 20; }, { water = 20; } ); }]
when it should be["menu": { drinks : ( { coke = 20; }, { pepsi : 20; }, { water : 20; } ); }]
the prints in the debugger shouldn't affect how the code works in your app. I realized I didn't have the returns on separate lines. does it work now?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.