0

I am on a difficult part of swing and after hours or investigations, I have found informations but not enough to perform what I look for. I'am sending a POST http request to a server, this one send me back a JSON converted as an NSDictionnary:

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

To see what the server send to me, I print this NSString:

let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
    println("**** response data = \(responseString)")

This is an example of what it can return to me:

**** response data = Optional({"result":true,"data":"[{\"id\":\"284ad166f8152268e4010c4cb21c40c13f195165\",\"due\":null,\"description\":\"\",\"status\":\"LATE\",\"summary\":\"tache late\",\"context\":\"\",\"folder\":\"INBOX\"},{\"id\":\"b43bd766295220b23279899d025217d18e98374a\",\"due\":null,\"description\":\"\",\"status\":\"IN-PROCESS\",\"summary\":\"tache in process\",\"context\":\"\",\"folder\":\"INBOX\"}]"}

What I look for, is separate these informations to get the Id on a string, the due on another, description on another, etc. to print them on a UITableView, one line per array.

I have found tons of tutorials, links, like https://github.com/dankogai/swift-json, http://owensd.io/2014/08/06/functional-json.html, https://github.com/thoughtbot/Argo or http://roadfiresoftware.com/2014/08/a-safer-approach-to-json-parsing-in-swift/but...

I'm brand new on swift coding, it's my first month with this language, I'm probably missing somethings very easy about this Json parsing...

Thank you for your help.

2
  • 1
    i strongly recommend swift-json library, i used it for instagram api, it rocks! Commented Jun 3, 2015 at 8:35
  • I have tried to use it but I don't succeed to applicate it to my JSON. I'll keep trying to work with. Commented Jun 3, 2015 at 9:00

3 Answers 3

1

You can either use SwiftyJson or do it manually. You get the json so you do not need to convert it to NSString. First unwrap the dictionary using

json!

Second you need to get stuff that you want. As you see you need to get the value from "data" key so get the value using

json!["data"]

Next you can access whatever you want

if let id = json!["data"]!["id"]! {
  println(id)
}

if let due = json!["data"]!["due"]! {
  println(due)
}

if let description = json!["data"]!["description"]! {
  println(description)
}

Now you can represent it in your UITableViewCell. As an example you can use id as the title and due & description as the content.

The only thing that matters here is to understand how to access key and value in a dictionary.

The better way to do this in order to stop repeating yourself is to store the value of data into a constant

let data = json!["data"]!

Then get your preferred stuff out of it. As an instance

if let id = data["id"]! {
  println(id)
}

Here's a small example to show you how to do it

let dict = Optional(["data": ["id": "12345", "due": "due date", "description": "some description"]])

let data = dict!["data"]!

println(data["id"]!)
// 12345
println(data["due"]!)
// due date
println(data["description"]!)
// some description

Edit: Add solution to the problem. The problem was with the way the JSON result was casted. Instead of as? NSDictionary use as? [AnyObject]

let serverJsonResponse = "[{\"id\":\"284ad166f8152268e4010c4cb21c40c13f195165\",\"due\":null,\"description\":\"\",\"status\":\"LATE\",\"summary\":\"tache late\",\"context\":\"\",\"folder\":\"INBOX\"},{\"id\":\"b43bd766295220b23279899d025217d18e98374a\",\"due\":null,\"description\":\"\",\"status\":\"IN-PROCESS\",\"summary\":\"tache in process\",\"context\":\"\",\"folder\":\"INBOX\"}]"

var error: NSError?

let json/*: [AnyObject]*/ = NSJSONSerialization.JSONObjectWithData(serverJsonResponse.dataUsingEncoding(NSUTF8StringEncoding)!, options: NSJSONReadingOptions.MutableContainers, error: &error) as [AnyObject]

// println(json)

// Before casting to [AnyObject]
// println(json as? [AnyObject])

// dump(json)

for dict in json {
    // dump(dict)

    println(dict["id"])
    println(dict["due"])
    println(dict["description"])

    // if let id = dict["id"] as? Int {
       // println(id)
    // }

    // if let due = dict["due"] as? String {
        // println(due)
    // }

    // if let description = dict["description"] {
        // println(description)
    // }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Comments are not for extended discussion; this conversation has been moved to chat.
1

If you are actually getting it back as an NSDictionary, you shouldn't need to convert it into anything else.

var responseDict = json!.objectForKey("data") as! NSDictionary
var idString = responseDict.objectForKey("id") as! String
var dueString = responseDict.objectForKey("due") as! String

1 Comment

Thank you for your answer. I have an error message on the first line: Could not cast value of type '__NSCFString' (0xd417ac) to 'NSDictionary' (0xd41d74). json is declared as NSDictionnary? and this his value: value __NSCFString *@"[{\"id\":\"284ad166f8152268e4010c4cb21c40c13f195165\",\"due\":null,\"description\":\"\",\"status\":\"LATE\",\"summary\":\"tache late\",\"context\":\"\",\"folder\":\"INBOX\"},{\"id\":\"b43bd766295220b23279899d025217d18e98374a\",\"due\":null,\"description\":\"\",\"status\":\"IN-PROCESS\",\"summary\":\"tache in process\",\"context\":\"\",\"folder\":\"INBOX\"}]"
1

Your JSON data field in the response is an array of dictionaries ([ is the start delimiter for a JSON array, { is the start delimiter for a JSON dictionary).

[{\"id\":\"284ad166f8152268e4010c4cb21c40c13f195165\",\"due\":null,\"descript‌​ion\":\"\",\"status\":\"LATE\",\"summary\":\"tache late\",\"context\":\"\",\"folder\":\"INBOX\"},{\"id\": ...

So, once you've got the global JSON response decoded with your existing line:

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

you just have to grab this part of the response like @iosDev82 explained, but you have to cast it as an array of dictionaries instead of a simple dictionary:

if let responseArray = json!.objectForKey("data") as? [[String:AnyObject]] {
    for dic in responseArray {
        let theID = dic["id"] as? String
        let theStatus = dic["status"] as? String
        // etc
    }
}

EDIT:

Mmmm, I knew your data reminded me of something... Have a look at this: https://stackoverflow.com/a/30570819/2227743 I already explained this problem to you. :)

You have to treat the data field as a String first, then decode the JSON it contains, then access its objects.

Decode JSON response > Get "data" field as String > Decode this JSON string > Access the objects

Example:

let dataFieldDecodedFromJSONAsString = "[{\"id\":\"284ad166f8152268e4010c4cb21c40c13f195165\",\"due\":null,\"description\":\"\",\"status\":\"LATE\",\"summary\":\"tache late\",\"context\":\"\",\"folder\":\"INBOX\"},{\"id\":\"b43bd766295220b23279899d025217d18e98374a\",\"due\":null,\"description\":\"\",\"status\":\"IN-PROCESS\",\"summary\":\"tache in process\",\"context\":\"\",\"folder\":\"INBOX\"}]"
let insideJSONStringReEncodedAsData = dataFieldDecodedFromJSONAsString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if let json2 = NSJSONSerialization.JSONObjectWithData(insideJSONStringReEncodedAsData!, options: nil, error: nil) {
    if let responseArray = json2 as? [[String:AnyObject]] {
        for dic in responseArray {
            let theID = dic["id"] as? String
            let theStatus = dic["status"] as? String
            // etc
        }
    }
}

1 Comment

Thanks, you helped me to understand what this JSON was. but I'm quite surprised, I'm not entering on the if conditions, the step by step goes out of the if once he underlines the condition

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.