JSON Handling

This is the second post in a series on accessing RESTful web services from the iPhone.
The example project used in this post can be downloaded here.

JSON

JSON has been around for about a decade now.  It has more recently become a popular alternative to XML because of both a smaller payload and a standardized format which focuses on associations and collections. WCF web services, for example, provide out of the box support for JSON as a data exchange format. After years of dealing with XML and various schemas, I prefer JSON's succinct style.


JSON + iPhone

As far as the iPhone is concerned, handling JSON is not currently built into any of the frameworks. For native development, there is nothing to specifically facilitate consuming or exporting JSON. However some people at Apple do recognize that JSON is widely used, as evident by both its support in Dashcode bindings and its use as the exchange format for APNs.

Because the JSON specification is extremely simple, this does not pose a problem for creating a JSON handling solution. The question always arises, should I find someone else's solution or roll my own? In my case, I take the lazy programmer approach. I am generally lazy unless I find the problem very interesting or I can't find something to suit my needs (in that order). Sometimes a problem *IS* very interesting and I want to solve it in my own way, as a personal challenge. Sadly business deadlines and schedules don't accommodate this very often. So to the end of being as lazy as possible, I found a very well written (complete with test cases!) JSON "library" that works on the iPhone.


BSJSONAdditions

I actually looked around at a couple of JSON handling "libraries" for the iPhone. BSJSONAdditions was the only one that had test cases and more than one contributor. What it lacked was specific support for EDM date types.  The JSON format does not have support for date as a first-class primitive type, only numbers and strings. Obviously no iPhone library I was going to find would have support for *THAT*, nor did I expect it to or even anticipate needing it (lesson learned there!). I will discuss EDM, EDM dates, and my additions to BSJSONAdditions [pun intended] in a later article.

This library translates JSON objects (name/value pairs) into NSDictionarys and JSON arrays into NSArrays. So given the following JSON:
{
											    "myCoolObject" : 
											    [ 
											        "value1", 
											        "value2" 
											    ]
											}
BSJSONAdditions would create an NSDictionary with one entry, "myCoolObject". The value for "myCoolObject"'s entry would be an NSArray with 2 values, "value1" and "value2". 


The Example

This article will build on the previous post's project. Those classes will be modified and extended, as well as adding the BSJSONAdditions to the project. The primary focus of the changes will be on parsing the JSON data and displaying it in a UITableView. 

If you have not yet downloaded the source for this example, you can do so here.

This post is not about explaining what a UITableView is or does and assumes you know how to use one. Please referring to UITableView docs for more information.
searchwindow
The Project

The only new files are those under the BSJSON group, now at the top of the project.

   
RestConnection 

This class has been slightly extended to incorporate the BSJSONAdditions. As a convenience, there is now a new property for returning the response body as a parsed dictionary.
// Returns a dictionary representation of the last data received.
											@property (nonatomic, readonly) NSDictionary *dictionaryData;
											
...
- (NSDictionary *)dictionaryData { return [NSDictionary dictionaryWithJSONString:[self stringData]]; }

SearchResultsViewController

This class has changed the most. The UITextView has been removed and replaced by a UITableView. The delegate and datasource have been set to the view controller.

The finishedReceivingData method has been changed to the following.
- (void)finishedReceivingData:(NSData *)data
											{
											    NSLog(@"finishedReceivingData: %@", [restConnection stringData]);
											    [activityIndicator stopAnimating];
											
// Get the dictionary containing the raw parsed data. NSDictionary *rawData = [restConnection dictionaryData];
// Get the interesting search results data for display to the user. [tableData release]; tableData = [[[rawData objectForKey:@"responseData"] objectForKey:@"results"] retain]; [mainTableView reloadData]; }

A parsed dictionary representation of the data is now retrieved instead of the raw JSON. We reach into the responseData and get the results which contain the interesting information that our UI wants to display, search result information.

The table view methods section has also been added. These methods are for the table datasource and delegate implementation. Basically for each result we display a table row that shows a search result description and it's URL. Thats it, pretty simple and straight forward.


Conclusion

This post has mostly talked about JSON and how to parse it on the iPhone. The next post for the series will talk more about connecting to an EDM backed web service and some of the challenges that have to be overcome in doing so.

Until next time, enjoy.

Even your worst day has a lesson to learn.