Search code examples
jsonswiftswift2httpresponsejsonserializer

How do I get values from a complex JSON object?


Is it possible that someone could show me how to get the names of these pizza places printing out? My application prints out the expected "Status Code: 200". However, my console only shows empty brackets []. I suspect that I am not pulling values from my JSON object properly.

I'm using this link for my API.

Link For API

Question

How can I properly fetch values from my serialized JSON object?

relevant code:

    // Response
    if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200, let data = data {
        print("Status Code: \(httpResponse.statusCode)")



        do {
            let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)

            if let pizzaPlaces = json["response"] as? [[String: AnyObject]] {
                for place in pizzaPlaces {
                    if let name = place ["name"] as? String {
                        self.PizzaClass.append(name)
                    }
                }
            }
        } catch {
            print("Error Serializing JSON Data: \(error)")
        }
        print(self.PizzaClass)


    }
}).resume()

Solution

  • You need to cast your NSJSONSerialization.JSONObjectWithData result as a [String:AnyObject].

        let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
    

    Once you have that all you need to do is pay attention to what you're casting. Take the code below for an example. If we want to get our response object using jsonObject["response"] what kind of data structure do we have?

    "response": {
            "venues": [{
                //... continues
            }]
        } 
    

    On the left we have "response" which is a string, on the right we have {} which is an AnyObject. So we have [String: AnyObject]. You just need to think about what object your dealing with piece by piece. Below is a working example that you can just paste into your application.

    full working code:

    func getJson() {
    
        let request = NSMutableURLRequest(URL: NSURL(string: "https://api.foursquare.com/v2/venues/search?client_id=0F5M0EYOOFYLBXUOKTFKL5JBRZQHAQF4HEM1AG5FDX5ABRME&client_secret=FCEG5DWOASDDYII4U3AAO4DQL2O3TCN3NRZBKK01GFMVB21G&v=20130815%20&ll=29.5961,-104.2243&query=burritos")!)
        let session = NSURLSession.sharedSession()
    
        request.HTTPMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Accept")
    
        let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
    
            guard let testResponse = response as? NSHTTPURLResponse else {
                print("\(response)")
                return
            }
    
            guard let status = HTTPStatusCodes(rawValue: testResponse.statusCode) else {
                print("failed to unwrap status")
                return
            }
            print(status)
    
            switch status {
            case .Created:
                print("ehem")
            case .BadRequest:
                print("bad request")
            case .Ok:
                print("ok")
    
                guard let returnedData = data else {
                    print("no data was returned")
                    break
                }
                do {
                    let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
    
                    guard let response = jsonObject["response"] as? [String: AnyObject] else { return }     
                    guard let venues = response["venues"] as? [AnyObject] else { return }
                    guard let location = venues[0]["location"] as? [String:AnyObject] else { return }
                    guard let formattedAddress = location["formattedAddress"] else { return }
    
                    print("response: \n\n \(response)\n------")
                    print("venues : \n\n \(venues)\n-------")
                    print("location : \n\n \(location)\n------")
                    print("formatted address : \n \(formattedAddress)")
    
                } catch let error {
                    print(error)
                }
    
                // update user interface
                dispatch_sync(dispatch_get_main_queue()) {
                    print("update your interface on the main thread")
                }
            }  
        }
        task.resume()
    }
    

    place this either in its own file our outside of the class declaration,

      enum HTTPStatusCodes : Int {
            case Created = 202
            case Ok = 200
            case BadRequest = 404 
        }