Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Parsing JSON with Objective-C

I followed along with the video when JSON was parsed. However, that JSON was done only at 1 level...meaning there was only one child for the parent (though there were multiple children). How would I get to attributes that are nested deeper in the JSON?

For example. The elements I am trying to get: Title: data.children[i].data.title Thumbnail: data.children[i].data.thumbnail Json: http://www.reddit.com/r/HistoryPorn/.json

6 Answers

Hi Amit,

First - thank you so much for your awesome tutorials. I am having a similar problem. I was able to easily get to the titles/author in your example using the team treehouse api. however, i am now trying to use this YouTube API:

https://gdata.youtube.com/feeds/api/users/CrossFitHQ/playlists?v=2&alt=json

I used the same methodology, but I think the error I'm getting has to do with the fact that I have dictionaries nested in arrays and I need to somehow specify which child is a dictionary and which is an array.

Ultimately, I'm trying to get the following fields from the "-entry":

"title" (the true title is also contained in a strange "$t" key) "content" > "src": essentially the url of the playlist

Thank you VERY VERY much, Amit Bijlani.

Amit Bijlani
STAFF
Amit Bijlani
Treehouse Guest Teacher

Glad you are enjoying the tutorials! These are very nested entries and you could use the method valueForKeyPath. So for example if your parsed data is stored in a dictionary called dictionary then you should be able to access it:

// entries is an array of dictionaries
NSArray* entries = [dictionary valueForKeyPath:@"feed.entry"];

NSDictionary *firstItem = [entries objectAtIndex:0];

NSString *title = [firstItem objectForKey:@"title"];
NSString *src = [firstItem objectForKey:@"src"];

The above code is not tested so I can't guarantee it works but it should give you the general idea. Once you have the entries array you can create your table view because it contains dictionaries with the related title/src.

thanks, Amit! I am able to see the title in the NSLog now. Huge step! I am now struggling with 2 things:

1) how do I get this printed into the tableview? Right now, the table view shows up empty.
2) how do I display all of the "titles" listed in the JSON. The objectAtIndex:0 restricts me to the first "title" in the dictionary. I have attached my code below. Thanks again for your help, sir:

  • (void)viewDidLoad { [super viewDidLoad]; NSURL *feedURL = [NSURL URLWithString:@"https://gdata.youtube.com/feeds/api/users/Crossfithq/playlists?v=2&alt=json"]; NSData *jsonData = [NSData dataWithContentsOfURL:feedURL]; NSError *error = nil; NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];

    NSArray *entry = [dataDictionary valueForKeyPath:@"feed.entry"]; NSDictionary *firstItem = [entry objectAtIndex:5]; NSString *title = [firstItem valueForKeyPath:@"title.$t"];

    NSLog(@"the title is %@", title); /* self.blogPosts = [dataDictionary valueForKey:@"sports"]; NSArray *dataArray = [dataDictionary valueForKey:@"leagues"]; self.leaguesDictionary = [dataArray valueForKey:@"name"]; */ }

  • (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }

pragma mark - Table view data source

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1; }

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [self.feeds count]; }

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    NSDictionary *feed = [self.feeds objectAtIndex:indexPath.row];

    cell.textLabel.text = [feed valueForKey:@"title"]; //cell.detailTextLabel.text = [blogPost valueForKey:@"uid"];

    return cell; }

  • (void)viewDidLoad { [super viewDidLoad]; NSURL *feedURL = [NSURL URLWithString:@"https://gdata.youtube.com/feeds/api/users/Crossfithq/playlists?v=2&alt=json"]; NSData *jsonData = [NSData dataWithContentsOfURL:feedURL]; NSError *error = nil; NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];

    NSArray *entry = [dataDictionary valueForKeyPath:@"feed.entry"]; NSDictionary *firstItem = [entry objectAtIndex:5]; NSString *title = [firstItem valueForKeyPath:@"title.$t"];

    NSLog(@"the title is %@", title); /* self.blogPosts = [dataDictionary valueForKey:@"sports"]; NSArray *dataArray = [dataDictionary valueForKey:@"leagues"]; self.leaguesDictionary = [dataArray valueForKey:@"name"]; */ }

  • (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }

pragma mark - Table view data source

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1; }

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [self.feeds count]; }

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    NSDictionary *feed = [self.feeds objectAtIndex:indexPath.row];

    cell.textLabel.text = [feed valueForKey:@"title"]; //cell.detailTextLabel.text = [blogPost valueForKey:@"uid"];

    return cell; }

sorry Amit ...i tried to do the code block...didn't work

Hi Amit Bijlani - thanks for your help...i just figured out how to load the array of entries using your valueForKeyPath recommendation. I also have it displaying on the tableView.

Thanks!

Amit Bijlani
Amit Bijlani
Treehouse Guest Teacher

Glad you figured out :)

Btw, when you paste, surround your code with three backticks followed by the name of the language "objective-c" on the line before it and three backticks on the line below it, like this:

```objective-c

NSString *test = @"this is a test";

```