Working with JSON in iOS 5 Tutorial

Ray Wenderlich
Learn how you can easily read and write JSON in iOS 5!

Learn how you can easily read and write JSON in iOS 5!

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.

descr

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).

descr

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:

descr

To polish up the interface add 3 more labels and finish the UI so it looks like this:

descr

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:

descr

Not bad for 3 lines of code, eh? :]

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:

descr

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:

descr

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.

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

User Comments

80 Comments

[ 1 , 2 , 3 , 4 , 5 , 6 ]
  • Hi,

    I'm super new when it comes to json and web services in general. I'm creating an app with the Grooveshark public API and in order to get the info I need it says I need to send a raw post json payload in order to get a list of songs. The example is similar to this:

    http://api.grooveshark.com/ws3.php?sig=cd3ccc949251e0ece014d620bbf306e7
    {"method":"getPopularSongsToday","header":{"wsKey":"key"},"parameters":[]}

    Through this tutorial I see how I can submit a request using just an url, but how do I add that second line when trying to fetch the data? Just adding it to the end of the url returns an error.

    Thank you!
    crstrater
  • i encounter the problem when using post, the error popped up that Warning, status code of response was not 200, it was 400
    2014-03-20 01:15:54.407 iBeacons[6669:60b] error parsing JSON response: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldnt be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x156b6440 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
    400 Required String parameter 'beaconsMapping' is not present Required String parameter 'beaconsMapping' is not present
    seashore115
  • hi

    please help me about Deserialization to class! how should Deserialization (json) with class?

    thanks for now
    maxinur
  • hi

    please help me about Deserialization to class!

    for example in .net you give json data Nsstring and give class name after it load in your custom class :
    Account Acc =(Account)JSON.deserialize(str, Account.class);

    how should Deserialization (json) with class?
    please please help
    thanks for now
    maxinur
  • Thanks for this! I'm new to ios apps and coding in general and this really helped. I was able to follow the tutorial and take it a step further by calling a local json file. The found out how to display more info from the json in a text box that scrolls.
    lasherm
[ 1 , 2 , 3 , 4 , 5 , 6 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in September: iOS 8 App Extensions!

Sign Up - September

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

  • Charlie Fulton

... 49 total!

Update Team

Editorial Team

  • Ryan Nystrom

... 23 total!

Code Team

  • Orta Therox

... 3 total!

Translation Team

  • Wilson Lin
  • Vitaliy Zarubin
  • Di Peng

... 33 total!

Subject Matter Experts

  • Richard Casey

... 4 total!