1

I found this question on parsing JSON in Swift 3 to be very helpful, but I noticed my JSON structure had an array for the "weather" key (see red arrow). I was able to parse other parts of the JSON output, but this array caused problems. Snapshot of Console

Question: Why am I not able to use the [String:Any] pattern that worked on other parts of this JSON data?.

This is my error in the console: Could not cast value of type '__NSSingleObjectArrayI' (0x112e04be0) to 'NSDictionary' (0x112e05108).

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=MYAPIKEY")!

        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if error != nil {
                print(error)
            }else {
                if let urlContent = data {
                    do {
                        let parsedData = try JSONSerialization.jsonObject(with: urlContent, options: .allowFragments) as! [String:Any]
                        print(parsedData)
                       let currentCondions = parsedData["main"] as! [String:Any]

                        for (key, value) in currentCondions {
                            print("\(key) - \(value)")
                        }

                        let locationInfo = parsedData["sys"] as! [String:Any]
                        for (key, value) in locationInfo {
                            print("\(key) - \(value)")
                        }

                        let weatherMain = parsedData["weather"] as! [String:Any]
                        print(weatherMain)

                    } catch {
                       print("JSON processessing failed")
                    }//catch closing bracket
                }// if let closing bracket
            }//else closing bracket
        }// task closing bracket
        task.resume()
    }
}
2
  • Your issue isn't clear. Where in your code specifically is your issue? What is the actual issue? Compile error? Runtime error? Unexpected results? Be specific. Commented Nov 28, 2016 at 22:13
  • I updated the code and the question to show the issue in console. I get a "Thread 8: signal SIGABRT" with the following error in the console: Could not cast value of type '__NSSingleObjectArrayI' (0x112e04be0) to 'NSDictionary' (0x112e05108). Commented Nov 28, 2016 at 22:17

1 Answer 1

3

The error makes the issue fairly clear (that, and looking at the output at the start of your question. The value for the "weather" key is not a dictionary. It's an array of dictionary.

So this:

let weatherMain = parsedData["weather"] as! [String:Any]

needs to be:

let weatherMain = parsedData["weather"] as! [[String:Any]]

As a side note, every use of ! in your app is a crash waiting to happen. You should be safely unwrapping and safely casting values that might not actually be what you think. I strongly suggest you spend some quality time reviewing the sections on optionals, type casting, and optional chaining in the The Swift Programming Language book.

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

1 Comment

thanks for the quick reply and explaining the dictionary vs. array of dictionary. This was my first attempt at JSON ever. Your answer was spot on. I am a learner and can get stumped easily. I'll take your advice on not force unwrapping. I should get in the habit of wrapping it in something with error handling.

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.