brickm brickm - 6 days ago 5
Swift Question

Parsing JSON with a nested array in Swift 3

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()
}
}

Answer

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.

Comments