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
Parsing Options
I’d like to talk just a bit more about NSJSONSerialization’s JSONObjectWithData:options:error: method. It’s one of these Apple APIs which understand and do everything by themselves, but you still can configure a bit its behavior.
Notice in the code that I chose to pass for the parameter options a value of kNilOptions. kNilOptions is just a constant for 0 – I find its name very descriptive though, so I always prefer it over just the value of 0 as a method parameter.
However you can pass other values or even a bit mask of values to combine them. Have a look at what you got as options when you’re converting JSON to objects:
- NSJSONReadingMutableContainers: The arrays and dictionaries created will be mutable. Good if you want to add things to the containers after parsing it.
- NSJSONReadingMutableLeaves: The leaves (i.e. the values inside the arrays and dictionaries) will be mutable. Good if you want to modify the strings read in, etc.
- NSJSONReadingAllowFragments: Parses out the top-level objects that are not arrays or dictionaries.
So, if you’re not only reading, but also modifying the data structure from your JSON file, pass the appropriate options from the list above to JSONObjectWithData:options:error:.
Displaying to the Screen
We’re going to continue by showing the latest loan information on the screen. At the end of “fetchedData:” method add these few lines of code:
// 1) Get the latest loan
NSDictionary* loan = [latestLoans objectAtIndex:0];
// 2) Get the funded amount and loan amount
NSNumber* fundedAmount = [loan objectForKey:@"funded_amount"];
NSNumber* loanAmount = [loan objectForKey:@"loan_amount"];
float outstandingAmount = [loanAmount floatValue] -
[fundedAmount floatValue];
// 3) Set the label appropriately
humanReadble.text = [NSString stringWithFormat:@"Latest loan: %@
from %@ needs another $%.2f to pursue their entrepreneural dream",
[loan objectForKey:@"name"],
[(NSDictionary*)[loan objectForKey:@"location"]
objectForKey:@"country"],
outstandingAmount];
The latestLoans array is a list of dictionaries, so (1) we get the first (and latest) loan dictionary and (2) we fetch few values about the loan. Finally (3) we set the text of the 1st label in the UI.
OK! Let’s have a look – hit Run and see what comes up:
Of course the information you see will be different as Kiva adds loans constantly – but it’s clear we achieved what we wanted, we parsed JSON data and visualized some human readable info.
Generating JSON Data
Now let’s do the opposite. From the loan NSDictionary that we now have we’ll build some JSON data, which we will be able to send over to a server, another app, or do with it whatever else we want.
Add this code to the end of the fetchedData: method:
//build an info object and convert to json
NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys:
[loan objectForKey:@"name"],
@"who",
[(NSDictionary*)[loan objectForKey:@"location"]
objectForKey:@"country"],
@"where",
[NSNumber numberWithFloat: outstandingAmount],
@"what",
nil];
//convert object to data
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:info
options:NSJSONWritingPrettyPrinted error:&error];
Here we build an NSDictionary called info where we store the loan information as who, where, and what in different keys and values.
Then we call dataWithJSONObject:options:error: – the opposite to the JSON API we just used before. It takes in an object and turns it into JSON data.
For the options parameter there’s only one possible value – NSJSONWritingPrettyPrinted. If you want to send the JSON over the Internet to a server use kNilOptions as this will generate compact JSON code, and if you want to see the JSON use NSJSONWritingPrettyPrinted as this will format it nicely.
So, at this point our job of turning info into JSON is finished, but we can’t be sure before we see that it is actually so. Let’s show the JSON into our second UI label. Add this final line of code to fetchedData:
//print out the data contents
jsonSummary.text = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
By initializing an NSString with initWithData:encoding: we easily get the text representation of our JSON data and we show it straight inside the jsonSummary label. Hit Run and:
Integrating Objects and JSON
Imagine if NSDictionary, NSArray, NSString, and NSData had methods to convert to and from JSON data – wouldn’t that be great?
Oh, but wait – we’re using it’s Objective-C, so we can actually extend foundation classes with methods of our own! Let’s do an example with NSDictionary and see how useful that could be.
Open ViewController.m, and add this category just above the @implementation:
@interface NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:
(NSString*)urlAddress;
-(NSData*)toJSON;
@end
@implementation NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:
(NSString*)urlAddress
{
NSData* data = [NSData dataWithContentsOfURL:
[NSURL URLWithString: urlAddress] ];
__autoreleasing NSError* error = nil;
id result = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
-(NSData*)toJSON
{
NSError* error = nil;
id result = [NSJSONSerialization dataWithJSONObject:self
options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
@end
As there’s nothing new that I didn’t speak about so far in this tutorial I won’t go over the code line by line.
But basically, we define 2 methods on NSDictionary: one dictionaryWithContentsOfJSONURLString: which gets an NSString with a web address (it’s often easier to work with URLs as text, not as NSURL instances), does all the downloading, fetching, parsing and whatnot and finally just returns an instance of a dictionary (or nil in case of an error) – ain’t that pretty handy?
In the category there’s also one more method – toJSON which you call on an NSDictionary instance to get JSON data out of it.
So with this category fetching JSON from the web becomes as easy as :
NSDictionary* myInfo =
[NSDictionary dictionaryWithContentsOfJSONURLString:
@"http://www.yahoo.com/news.json"];
And of course on any of your NSDictionary objects you can do:
NSDictionary* information =
[NSDictionary dictionaryWithObjectsAndKeys:
@"orange",@"apple",@"banana",@"fig",nil];
NSData* json = [information toJSON];
Pretty cool and readable code. Now of course you can also extend NSMutableDictionary with the same dictionaryWithContentsOfJSONURLString: method, but in there you’ll have to pass NSJSONReadingMutableContainers as options – so hey, NSMutableDictionary could be initialized with JSON too, and it’ll hold mutable data. Cool!
Where to Go From Here?
Here is a example project with all of the code from the above tutorial.
At this point, you have hands-on experience with the awesome new iOS5 JSON reading and writing APIs, and are ready to start using this in your own apps!
Before we go though, I want to mention just few more methods from the NSJSONSerialization class.
BOOL isTurnableToJSON = [NSJSONSerialization
isValidJSONObject: object]
As you might guess, isValidJSONObject: tells you whether you can successfully turn a Cocoa object into JSON data.
Also I presented to you the 2 methods to read and write JSON from/to NSData objects, but you can do that also on streams – with JSONObjectWithStream:options:error: and writeJSONObject:toStream:options:error:, so do have a look at the class documentation.
If you want to keep playing around with JSON, feel free to extend the demo project with the following features:
- Modify the demo project to use the JSON categories, like we discussed above
Develop further JSON categories for NSArray, NSString, etc - Think about how cool it’d be if your classes had a toJSON method – so you can easily persist them on your web server!
- Make an implementation on a test class to see if you can get it working!
This is an example of one of the “bonus” chapters from our new book iOS 5 By Tutorials. The bonus chapters like this one cover some of the cool but easily overlooked new APIs in iOS 5 like the new Address Book APIs, new Location APIs, new Calendar APIs, and much more, so if you want to learn more about iOS 5 check it out!
If you have any questions, comments, or suggestions, please join in the forum discussion below!
This is a blog post by iOS Tutorial Team member Marin Todorov, a software developer with 12+ years of experience, an independant iOS developer and the creator of Touch Code Magazine.