Working with JSON in iOS 5 Tutorial
Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, check out iOS 5 by Tutorials Second Edition! Note from Ray: This is the eighth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 […] By Ray Wenderlich.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Working with JSON in iOS 5 Tutorial
20 mins
Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, check out iOS 5 by Tutorials Second Edition!
Note from Ray: This is the eighth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 By Tutorials. Enjoy!
This is a blog post by iOS Tutorial Team member Marin Todorov, a software developer with 12+ years of experience, an independent iOS developer and the creator of Touch Code Magazine.
iOS 5 has some new built-in APIs to make it really easy to read and write JSON.
If you don’t know what JSON is, it’s a simple human readable format that is often used to send data over a network connection.
For example, if you have an array of three strings, the JSON representation would simply be:
["test1", "test2", "test3"]
If you have a Pet object with member variables name, breed, and age, the JSON representation would simply be:
{"name" : "Dusty", "breed": "Poodle", "age": 7}
It’s that simple, which is why it’s so easy and popular to use. For the full spec, which can be read in just a couple minutes, check out www.json.org.
The reason JSON is important is that many third parties such as Google, Yahoo, or Kiva make web services that return JSON formatted data when you visit a URL with a specified query string. If you write your own web service, you’ll also probably find it really easy to convert your data to JSON when sending to another party.
In this tutorial, we’ll cover how you can work with JSON in iOS 5. Keep reading to see how simple it is!
JSON and iOS 5
If you’ve had to parse JSON in your iOS apps in the past, you’ve probably used a third party library such as JSON Framework.
Well with iOS 5, needing to use a third party library for JSON parsing is a thing of the past. Apple has finally added a JSON library in Cocoa and I must say I personally like it very much!
You can turn objects like NSString, NSNumber, NSArray and NSDictionary into JSON data and vice versa super easily. And of course no need to include external libraries – everything is done natively and super fast.
In this chapter we’re going to get hands-on experience with the new native JSON support. We’re going to build a simple application which will connect to the Internet and consume JSON service from the Kiva.org web site. It will parse the data, show it in human readable format on the screen, and then build back a different JSON.
Later on in the chapter we’re going to create a class category which will give you ideas how to integrate JSON support more tightly into Cocoa and your own classes. Having the possibility to turn your own classes data into JSON could really help you persist data structures online, exchange data between applications, or anything that requires your classes to be able to serialize and persist data, which can be sent over http, email, etc.
Getting Started
Open up Xcode and from the main menu choose File\New\New Project. Choose the iOS\Application\Single View Application template, and click Next. Name the product KivaJSONDemo, select iPhone for the Device family, and make sure just the Use Automatic Reference Counting checkbox is checked, click Next and save the project by clicking Create.
Let’s do a little bit of clean up first – open up ViewController.m file and replace everything inside with this :
#define kBgQueue dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
#define kLatestKivaLoansURL [NSURL URLWithString:
@"http://api.kivaws.org/v1/loans/search.json?status=fundraising"] //2
#import "ViewController.h"
@implementation ViewController
@end
In the first line of code we define a macro that gives us back a background queue – I like having a kBgQueue shortcut for that, so I can keep my code tighter.
In the second line of code we create a macro named kLatestKivaLoansURL which returns us an NSURL pointing to this URL [http://api.kivaws.org/v1/loans/search.json?status=fundraising].
Go ahead and visit this URL in your browser if you want – you’ll see Kiva.org’s list of currently fundraising loans in JSON format. We’re going to use this API to read the list of loans, take the latest one and show the information on the screen.
Let’s make a little detour and design the application’s UI in Interface Builder real quick.
Open ViewController.xib in the Project Navigator. This app is supposed to be positive and life-changing, so we need to do something about that background! Select it and from the Utilities bar (1), make sure you have the Attributes Inspector open (2), and set the Background to a nice green color (3).
Now grab a label from the Object library and drop it inside the already open view (1). Resize the label so it fits about 4 lines of text and takes almost the screen’s width (2). Then from the Attributes Inspector make the following changes: set “Background” to white, set “Lines” to “5” (3). Click on the label to make sure it’s selected and then press Cmd+C, Cmd+V to clone the label (4). Finally arrange the two labels like on the screenshot:
To polish up the interface add 3 more labels and finish the UI so it looks like this:
The only thing left is to connect our labels to a couple of IBOutlets in our class. Switch to ViewController.h and add two instance variables inside the interface:
@interface ViewController : UIViewController {
IBOutlet UILabel* humanReadble;
IBOutlet UILabel* jsonSummary;
}
Then open up ViewController.xib again. Control-drag from “File’s owner” onto the 1st 5-line label and from the popup menu choose humanReadable.
Again while holding the “ctrl” key drag with the mouse from “File’s owner” onto the 2nd 5-line label and from the popup menu choose jsonSummary.
That concludes the project setup – we’re ready to start coding!
Parsing JSON from the Web
The first thing we need to do is download the JSON data from the web. Luckily, with GCD we can do this in one line of code! Add the following to ViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
kLatestKivaLoansURL];
[self performSelectorOnMainThread:@selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
Remember how earlier we defined kBGQueue as a macro which gives us a background queue?
Well this bit of code makes it so that when viewDidLoad is called, we run a block of code in this background queue to download the contents at the Kiva loans URL.
When NSData has finished fetching data from the Internet we call performSelectorOnMainThread:withObject:waitUntilDone: so we can update the application’s UI. We haven’t written fetchedData: yet but will do so shortly.
Remember it is only OK to run a synchronous method such as dataWithContentsOfURL in a background thread, otherwise the GUI will seem unresponsive to the user.
Also, remember that you can only access UIKit objects from the main thread, which is why we had to run fetchedData: on the main thread.
Note: You might wonder why I preferred to use performSelectorOnMainThread:withObject:waitUntilDone: over dispatching a block on the main thread? It’s a personal preference really and I have two reasons:
I’m all for the greatest readability of a piece of code. For me, [self performSelectorOnMainThread:…] makes it easier to spot what’s going on in that piece of code.
I’m a symmetry freak! I find that Xcode doesn’t handle text indentation well when you use dispatch_async(), so purely visually the code is not so pleasant to look at.
You might have other preferences, so yes – if you prefer dispatch_async(dispatch_get_main_queue(), ^(){…}); go for it!
So, when the data has arrived the method fetchedData: will be called and the NSData instance will be passed to it. In our case the JSON file is relatively small so we’re going to do the parsing inside fetchedData: on the main thread. If you’re parsing large JSON feeds (which is often the case), be sure to do that in the background.
So next add the fetchedData method to the file:
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json objectForKey:@"loans"]; //2
NSLog(@"loans: %@", latestLoans); //3
}
This is it – the new iOS 5 JSON magic!
Basically iOS 5 has a new class named NSJSONSerialization. It has a static method called JSONObjectWithData:options:error that takes an NSData and gives you back a Foundation object – usually an NSDictionary or an NSArray depending what do you have at the top of your JSON file hierarchy.
In Kiva.org’s case at the top there’s a dictionary, which has a key with list of loans. In line 1, we get an NSDictionary from the JSON data. In line 2, we get an NSArray latestLoans which is the loans key in the top JSON dictionary.
Finally in line 3, we dump latestLoans to the console, so we’re sure everything’s OK. Hit Run and check Xcode’s console to see the result:
Not bad for 3 lines of code, eh? :]