Thursday, 1 August 2013

Accessing JSON Stored in NSDictionary

I'm still learning to be a developer... and probably always will be.  It helps me to write blogs about code that I manage to get working. I've written an app that uses OAuth to access a JSON input from the web and parse it. This post describes some of the new stuff I learnt on the way, specifically about parsing JSON and accessing NSDictionary.
In a previous post I describe how to lever out tweets from twitters' new API1.1 which now only outputs JSON (XML no longer possible).

 The key line that starts the process of making the data available in Cocoa/Objective-C is:

       jsonResponse = [NSJSONSerialization JSONObjectWithData:data
                                                       options:0
                                                         error:&error];
jsonResponse is of type NSDictionary which can be manipulated easily within the rest of your code.  I took me a little while to realise this - it looked like JSON when quickly glanced at by the untrained/lazy eye!

Dealing with NSDictionary

There are a couple of ways to get at the data in a NSDictionary that I considered, direct and valueForKeyPath.

I will use a nested dictionary as an example (a partial representation of Twitter's JSON output as a dictionary):
statuses = (
   { created_at = "time/date of message";

      id = big number;

      id_str = "big number";

      retweeted = 0;

      entities = { hashtags = ({text = <hashtag1>}, {text = <hashtag2>});

                       media = ({media_url = "url"},{media_url_https = "https url"});

                       urls = ({expanded_url = <full url1>}, {expanded_url2});

                    };

      user = { created_at = "time/date author signed up";

                       name = "author name";

                       profile_image_url = "url";

                       screen_name = "screen name";

                };

   },

   { created_at = "time/date of message;

      rest of next status...

   }, etc. etc.

NSDictionary *statusDict = [[NSDictionary alloc] init];
statusDict = [JSONResponse objectForKey:@"statuses"];

Direct NSDictionary Access

Really fast to process once compiled, difficult to read for humans
tweetId = [statusDict objectForKey:@"id"];

authorName = [[statusDict objectForKey:@"user"] objectForKey:@"name"];

imageWidth = [[[[[statusDict objectForKey:@"entities"] objectForKey:@"media"] objectForKey:@"sizes"] objectForKey:@"large"] objectForKey:@"w"];

NSDictionary valueForKeyPath Access

Really, really slow to process but very easy to code and read for humans.
tweetId = [statusDict valueForKeyPath:@"id"];

authorName = [statusDict valueForKeyPath:@"user.name"];

imageWidth = [statusDict valueForKeyPath:@"entities.media.sizes.large.w"];

A couple of links

Apple's NSDictionary Class Reference
I got my info on performance from Benedikt Terhechte's post on the performance of NSDictionary access methods.