Ranknoodle
Ranknoodle

Reputation: 897

Swift with Nested Json - Accessing Keys that are Not Strings

I'm trying to access keys in my API request (Nested Json) in Swift but the issue I'm having is that some of the keys in the NSDictionary are Strings with " and some keys don't have ". The keys that don't have " (not strings) I can not access.

What I would like is to have all the keys in the NSDictionary be a String or NSString so that I can access the data.

Output from API server.

API data as JSON Sting

{"id":1,"first_name":"joe","last_name":"blow","email":"[email protected]","api_authtoken":"qtgfLxuzaEJoJoLkZjdWt","authtoken_expiry":"2015-11-19T06:12:45.000Z","avatar_file_name":"1-1447697130.jpg","avatar_content_type":"image/png","avatar_file_size":516066,"avatar_updated_at":"2015-11-16T18:05:30.000Z","uid":null,"latitude":null,"longitude":null,"address":null,"city":null,"state":null,"country":null,"postal_code":null,"phone_number":null,"belt":null,"fbid":null,"badges":[{"id":1,"user_id":1,"badge_type_id":1,"created_at":"2015-11-18T17:34:43.000Z","updated_at":"2015-11-18T17:34:43.000Z","badge_url":"http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge1.png"},{"id":2,"user_id":1,"badge_type_id":2,"created_at":"2015-11-18T17:34:43.000Z","updated_at":"2015-11-18T17:34:43.000Z","badge_url":"http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge2.png"},{"id":3,"user_id":1,"badge_type_id":3,"created_at":"2015-11-18T17:34:43.000Z","updated_at":"2015-11-18T17:34:43.000Z","badge_url":"http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge3.png"},{"id":4,"user_id":1,"badge_type_id":4,"created_at":"2015-11-18T17:34:43.000Z","updated_at":"2015-11-18T17:34:43.000Z","badge_url":"http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge4.png"}]}

Convert the API Data into a NSDictionary

let responseDict = try! NSJSONSerialization.JSONObjectWithData(data,
            options: NSJSONReadingOptions.AllowFragments) as! NSDictionary

The corresponding NSDictionary is as follows:

PRINTING NSDICTIONARY = {
address = "<null>";
"api_authtoken" = qtgfLxuzaEJoJoLkZjdWt;
"authtoken_expiry" = "2015-11-19T06:12:45.000Z";
"avatar_content_type" = "image/png";
"avatar_file_name" = "1-1447697130.jpg";
"avatar_file_size" = 516066;
"avatar_updated_at" = "2015-11-16T18:05:30.000Z";
badges =     (
            {
        "badge_type_id" = 1;
        "badge_url" = "http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge1.png";
        "created_at" = "2015-11-18T17:34:43.000Z";
        id = 1;
        "updated_at" = "2015-11-18T17:34:43.000Z";
        "user_id" = 1;
    },
            {
        "badge_type_id" = 2;
        "badge_url" = "http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge2.png";
        "created_at" = "2015-11-18T17:34:43.000Z";
        id = 2;
        "updated_at" = "2015-11-18T17:34:43.000Z";
        "user_id" = 1;
    },
            {
        "badge_type_id" = 3;
        "badge_url" = "http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge3.png";
        "created_at" = "2015-11-18T17:34:43.000Z";
        id = 3;
        "updated_at" = "2015-11-18T17:34:43.000Z";
        "user_id" = 1;
    },
            {
        "badge_type_id" = 4;
        "badge_url" = "http://newappy-dev.s3-us-west-1.amazonaws.com/badges/badge4.png";
        "created_at" = "2015-11-18T17:34:43.000Z";
        id = 4;
        "updated_at" = "2015-11-18T17:34:43.000Z";
        "user_id" = 1;
    }
);
belt = "<null>";
city = "<null>";
country = "<null>";
email = "[email protected]";
fbid = "<null>";
"first_name" = joe;
id = 1;
"last_name" = blow;
latitude = "<null>";
longitude = "<null>";
"phone_number" = "<null>";
"postal_code" = "<null>";
state = "<null>";
uid = "<null>";

}

What I would like to do is iterate over the "badges" data in json.

I access the badges data like so:

dictionary.objectForKey("badges")

However I not getting the data. What am I doing wrong here? Thanks!

Upvotes: 0

Views: 2302

Answers (2)

Janusz Chudzynski
Janusz Chudzynski

Reputation: 2710

Said was few minutes faster than me. I was just writing example of how to accomplish it:

Swift 1.2

if let
    jsonData = NSData(contentsOfFile: jsonPath),
    json = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as? [String: AnyObject]
{
    if let badges = json["badges"] as? [AnyObject]{
        for badge in badges{
            println(badge)
        }

    }
}

Swift 2.0

let path = NSBundle.mainBundle().bundlePath as NSString // it needs be NSString, Swift String doesn't have stringByAppendingPathComponent method
let jsonPath = path.stringByAppendingPathComponent("data.json")


do{
    if let jsonData = NSData(contentsOfFile: jsonPath){
        let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options:NSJSONReadingOptions.AllowFragments)
        if let badges = json["badges"] as? [AnyObject]{
            for badge in badges{
                print(badge)
                //or process it in any other way
            }

        }

    }
}catch let error as NSError {
    print(error)
}

Upvotes: 2

Said Sikira
Said Sikira

Reputation: 4533

Your badges key contains an array of dictionaries, therefore you should use:

let badges = dictionary.objectForKey("badges") as? [[String:AnyObject]]

Since objectForKey: returns AnyObject? we can use it to construct array of dictionaries with String as a key and AnyObject as a values. When you get the array you can iterate through it and get values you need.

I would suggest moving from Objective C NSDictionary type to Swift native Dictionary. That would enable you to use subscripts and deal with your code in an easier fashion.

Upvotes: 2

Related Questions