Parsing JSON in iOS

This is a quick guide to parsing a JSON file in iOS, specifically on the iPhone. I’m not going to go into any detail about the history of JSON or why it’s used in preference to, say, XML. If you want to find out more about JSON then check out the following resources:

http://www.json.org/
http://www.w3schools.com/json/

The use of JSON as a serialisation format has grown in popularity as more and more third parties such as Google, Yahoo, and Twitter provide web services that return JSON formatted data from a given URL appended with a query string. For example, you can get the weather for London from the following URL and appended query (the “q=London,uk” part):

http://api.openweathermap.org/data/2.5/weather?q=London,uk

At the time of writing the returned JSON looks like this:

In order to make some sense of this, the iOS developer needs to parse this information and structure it into model data for their application so it can be usefully displayed. It turns out that from iOS 5 onwards, Apple have implemented a relatively simple framework for reading a JSON stream from a given URL (local or on-line) and parsing that stream into information that can be used in an iOS application.

For the following example I’ve put together a JSON file containing some information about six places of interest. Here’s what the file looks like:

To demonstrate parsing this JSON file, I’ve created a simple iPhone project that reads in the file, parses it and creates a “Location” class for each location entry declared in the JSON. This is then displayed as a list in a table view controller which then links to a detail view controller displaying more information together with a map and a map pin (annotation) showing the location of the selected place.

The example Xcode project is hosted at GitHub and you can either clone it or download it from here:

https://github.com/Phillipus/JSONHandler

(Note that I’ve set up this project to run on iOS 7. You’ll also need to be using Xcode 5.)

Load the project into Xcode and run it in the iOS simulator. When you see the first screen you’ll see a simple table displaying six location names and places:

JSON data in table format

JSON data in table format

Selecting a row in the table view initiates a segue to a new view controller that displays more detail about the location and a pin on a map:

JSON data

JSON data

Let’s examine how we load and display the raw JSON data in the application, starting at the point where the first table is displayed.

Open up the LocationsViewController.m class file and take a look at the viewDidLoad method:

viewDidLoad is the method that’s called when the Table View Controller is first created and displayed, so this is a good place to load the JSON data file. First we create a new instance of the class JSONLoader, which we’ll look at soon, and then a URL which is the location of our JSON file. If the JSON file was located online you would create an online URL here, but for this example we’re using a local file as this ensures we can run the project without any connection issues. Once we’ve done this, we call the locationsFromJSONFile: method on the JSONLoader instance. This will return an NSArray of Location objects that we can then use as a data source to display in the table. Notice that the NSArray instance variable, _locations, has been declared in the first line of the implementation:

Once the array of Location objects has been returned by the call to locationsFromJSONFile:, we then ask the table view to reload its data. This will in turn trigger the call of the Table View Controller methods, tableView:cellForRowAtIndexPath: and tableView:numberOfRowsInSection: which will supply the information needed to display the rows in the table.

Notice that the method call locationsFromJSONFile: is dispatched on a queue. This ensures that the operation to connect to the URL and fetch the JSON data is performed on a background thread so that we don’t block the UI. Once the data has been received we can then load the data in the table on the main UI thread by calling performSelectorOnMainThread:withObject:waitUntilDone:. The golden rule in iOS is that all UIKit objects methods should be accessed on the main thread.

The over-ridden method prepareForSegue:sender: simply ascertains which row in the table was selected and passes on the corresponding Location object to the target destination View Controller. This destination view, LocationDetailViewController, then displays the information in the Location object in a set of text fields and as a pin on a map.

Now that we know how the JSON data is loaded and presented to the user in a table view, let’s look under the hood at the model classes that do the work of parsing the contents of the JSON file and turning it into something that we can use in the application. Open the class file, JSONLoader.m and look at the following code:

The NSURLRequest and NSURLConnection part of the code is pretty much the standard approach to getting data from a given URL. We are using the static method sendSynchronousRequest rather than an asynchronous call because the whole method is being called on a queue as we saw earlier. The magic happens in this line:

The NSJSONSerialization class has a static method, JSONObjectWithData:options:error, which parses an NSData object and returns a Foundation object. This is typically an NSDictionary or an NSArray depending on how the JSON data is structured. The example locations.json file is structured as a dictionary consisting of one key, “locations”, mapped to an array of dictionary values. We access the array with the following line:

We can then iterate through the NSDictionary objects in the array creating one Location class object for each dictionary entry:

We then add this to a NSMutableArray of locations and return it when the method finishes.

Here’s the Location class header file:

And the Location class implementation file:

The Location class is simply a set of properties that map to the key names that are found in the location.json file. If you recall, the first set of data looks like this:

So, by writing code like this:

we are effectively assigning values to the properties in the Location class:

title = “The Pump Room”
place = “Bath”

and so on. (Note that the instance variables are prefixed with underscores. Because the properties are readonly we can only assign values directly to the underlying instance variables which are automatically synthesised for us).

We now have all of the information for a location encapsulated conveniently in a model class, Location.

If we take a look at the LocationDetailViewController.m class file we can see that in the viewDidLoad method we access all of these properties to populate the fields in the view. Note that the boolean value for “visited” is a NSNumber type which has to be converted to a BOOL type in order to set the value for the UISwitch control. The latitude and longitude properties are also NSNumber objects and these have to be converted to double values to create the coordinates for the map pin.

Wrap up

This post has, I hope, given you a start with parsing JSON and mapping the data to a simple model class. Of course, the structure and hierarchy of your own model classes will depend on the structure of the data in whatever JSON file or stream that you are working with.

Share this...Tweet about this on TwitterShare on LinkedInShare on Facebook

16 thoughts on “Parsing JSON in iOS

  1. HI Phillipus!!
    Very good job, I love your proyect but Im crazy with one thing.
    How Can I put all the pins in all directions of the json in the same map? I want to have, one table like yours but I want to have one big map with all the markers.
    Thanks!!!!!!!!

  2. Hi Philipus
    I am new bee to IOS . You work is awesome, that’s what I was looking for. Thank you. One question how can we update json file from server? (php) thank you…

  3. When I open the app without the internet connection, I’m getting this error: *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘data parameter is nil’. How can I fix it?

    Thanks a lot.

  4. Thanks so much for this tutorial. I have been able to use this example to setup an app. But I can’t figure out how to implement a search bar into the table view controller to filter when there are hundreds of table elements. Do you have an example with that implemented?

  5. thanks for creating an excellent tutorial! I have a question. I m trying to implement it for an app but I need to use an online Json.
    I changed in Locationsviewcontroller.m the path. I now have NSURL *url = [NSURL URLWithString :@”http://mysite.com/jsonoutput.php”];
    I get no errors or warnings but when i compile the app it stops unexpectedly. Is there another way to put a url for the file?
    thanks in advace

  6. I am able to show type,business_name using your code. But i can’t show of business_address’s city,state,zip. My Json is like this:

    {
    “meta”: {
    “rowCount”: 81
    },
    “result”: [
    {
    “type”: “organization”,
    “business_name”: “VIRGINIA MASON MEDICAL CENTER”
    “business_address”: {
    “city”: “SEATTLE”,
    “state”: “WA”,
    “zip”: “98101”,
    },
    “enumeration_date”: “2005-06-13T00:00:00.000Z”,
    “last_update_date”: “2012-05-30T00:00:00.000Z”,
    “organization_official”: {
    “last_name”: “TRUONG”,
    “first_name”: “HUNG”,
    “middle_name”: “VAN”,
    },

    },

    Thanks in advance

    • That’s because “business_address” is a NSDictionary. You have to extract city, state, and zip from the “business_address” NSDictionary.

  7. Hi Phillipus,

    Nice work………………..thanks for this tutorial……………….

  8. Risolto basta modificare il file JSONLoader.m
    Nella righa NSURLRequest *request = [NSURLRequest requestWithUrl: [NSRUL URLWithString:@”http://mywebsite.com/filejson”] e il resto lasciarlo senza modifiche

  9. Hi Phillipus,

    Great tutorial!!
    If you would want to sort the tableview rows by the location title (alphabetically), how would you do that?

    Thanks

  10. Pingback: ios 3 | dnmk.us

Comments are closed.