user2563039 user2563039 - 11 months ago 176
Swift Question

Correctly Parsing JSON in Swift 3

I'm trying to fetch a JSON response and store the results in a variable. I've had versions of this code work in previous releases of Swift, until the GM version of Xcode 8 was released. I had a look at a few similar posts on StackOverflow: Swift 2 Parsing JSON - Cannot subscript a value of type 'AnyObject' and JSON Parsing in Swift 3.

However, it seems the ideas conveyed there do not apply in this scenario.

How do I correctly parse the JSON reponse in Swift 3?
Has something changed in the way JSON is read in Swift 3?

Below is the code in question (it can be run in a playground):

import Cocoa

let url = ",122.048951"

if let url = NSURL(string: url) {
if let data = try? Data(contentsOf: url as URL) {
do {
let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments)

//Store response in NSDictionary for easy access
let dict = parsedData as? NSDictionary

let currentConditions = "\(dict!["currently"]!)"

//This produces an error, Type 'Any' has no subscript members
let currentTemperatureF = ("\(dict!["currently"]!["temperature"]!!)" as NSString).doubleValue

//Display all current conditions from API

//Output the current temperature in Fahrenheit

//else throw an error detailing what went wrong
catch let error as NSError {
print("Details of JSON parsing error:\n \(error)")

Answer Source

First of all never load data synchronously from a remote URL, use always asynchronous methods like URLSession.

'Any' has no subscript members

occurs because the compiler has no idea of what type the intermediate objects are (for example currently in ["currently"]!["temperature"]) and since you are using Foundation collection types like NSDictionary the compiler has no idea at all about the type.

This code uses URLSession and exclusively Swift native types

let urlString = ",122.048951"

let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
  if error != nil {
  } else {
    do {

      let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
      let currentConditions = parsedData["currently"] as! [String:Any]


      let currentTemperatureF = currentConditions["temperature"] as! Double
    } catch let error as NSError {


To print all key / value pairs of currentConditions you could write

 let currentConditions = parsedData["currently"] as! [String:Any]

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