I am having trouble parsing JSON that is returned from the NSURL session. What am I doing wrong?

535 views Asked by At

I'm successfully making a POST request and getting data back in return. I can then print that statement in the form of an NSString, after converting of course.

However, I want to save the returned json in usable variables/constants so I can display in the next subsequent screens. I'm having trouble getting various JSON parsing code to work.

I think some of my weaknesses is not understanding the form of 'data', that is returned when I use the NSURLSession. I used code I found elsewhere, and don't quite grasp what the return types are. Is that data from the code below in JSON? NSData?

Anyways, this script works until I start parsing through the data, trying to make sense of how to abstract the array.

If it helps my console returns my print statements (after converting to a NSString) as such:

Optional({
  "result":   {
  "girl": "monica",
  "waist": 22.0,
  "hair": "Brunette",
  "location": "Los Angeles"
  }
})

When I try and use the NSJSON serialization framework, the output of that object looks like this, which is supposedly an NSDictionary?:

{
result:   {
  girl: monica;
  waist: 22.0;
  hair: Brunette;
  location: "Los Angeles";
  }
}

A few things confuse me. Why did the quotation marks go away, and what is the optional and extra "result" attribute... Here's my code starting from NSURL request to end of code

    let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:5000")!)
    request.HTTPMethod = "POST"
    let postString = "color=\(finalDataPassed)&type=\(thirdDataPassed)&hair=\(dataPassed)&location=\(secondDataPassed)"

    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            println("error=\(error)")
            return
        }

        println("response = \(response)")

        let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)

        println(responseString)
        var error: NSError?

        let result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
            as? NSDictionary

        if(error != nil) {
            println(error!.localizedDescription)
            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("Error could not parse JSON: '\(jsonStr)'")
        }
        else {
            if let parseJSON = result {

                println(parseJSON)
                for item in parseJSON { // loop through data items
                    let obj = (item as! NSDictionary).objectForKey("result") as! NSDictionary
                    for (key, value) in obj {
                        println("Property: \"\(key as! String)\"")
                    }
                }

            }
            else {

                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                println("Error could not parse JSON: \(jsonStr)")

            }
        }
2

There are 2 answers

7
Icaro On

You have an dictionary inside a dictionary:

{
result: <- Key first dictionary    
  {
  girl: monica; <- start of second dictionary
  waist: 22.0;
  hair: Brunette;
  location: "Los Angeles"; <- end of second dictionary
  }
}

For a generic approach you can use:

   for item in dataArray { // loop through data items
        let obj = item.first as! NSDictionary
        for (key, value) in obj {
            println("Property: \"\(key as! String)\"")
            for (key2, value2) in (value as NSDictionary){
                println("Property: \"\(key2 as! String2)\"")
            }
        }
    }

In your case because the first dictionary is just one key you can retrieve it directly instead use the first for loop:

for item in dataArray { // loop through data items
    let obj = (item.first as! NSDictionary).objectForKey("result") as NSDictionary
    for (key, value) in obj {
        println("Property: \"\(key as! String)\"")
    }
}
1
Peter Kuhar On

Optional (they ? in code) means that the it can be nil. Check Swift Basics

The quotes went away because it's a printout of an NSDictionary which does not print out in a JSON format.

Note: To make things safer since you never know what server can return:

if let dataArray = result["result"] as NSArray{
      //your code
}