JSON (Javascript Object Notation) is a lightweight data format which has far less overhead then xml and is supported by a wide variety of programming languages. Detailed information on the specification can be found here (http://www.json.org/). In a nutshell JSON uses a combination of braces, quotes colons and commas to delineate fields. When returning large datasets this is a substantial savings over the open and close tags of xml.
Here is an example return from a database.
{"users": [{"id":"1", "userid":"fhardy", "firstname":"Frank", "lastname":"Hardy", "email":"fhardy@hauntedclock.com"}, {"id":"2", "userid":"jhardy", "firstname":"Joe", "lastname":"Hardy", "email":"jhardy@hauntedclock.com"}]}
Notice that each row is contained within a set of braces, and the associative array of fields is presented in the format of "fieldname":"fieldvalue". Many other json data examples can be seen here : http://labs.adobe.com/technologies/spry/samples/data_region/JSONDataSetSample.html.
Now that we have seen what JSON looks like lets create a simple database and php page which queries it and returns the data via json.
1. Install MAMP Server Software
If you do not already have a working php 5.2+ and mysql stack, download the MAMP package (http://www.mamp.info), follow the install instructions and confirm that it is working by bringing up the MAMP page (Show Start Page from the MAMP app).
2. Configure Database
Now that we have a functional MYSSQL and PHP stack we will now create the database and table. If you have a db and user you prefer to use you can skip this step.
1. From the Mamp page choose phpmyadmin
2. From the sidebar menu - Choose Privileges
3. Click the Add a New User button
Set the user name to json
Set the host to localhost
Set the password to json1
Make sure create database with same name and grant all privileges is checked.
Click Go at the bottom of the screen.
You will now have a new user created for your mysql database and a new database named json appearing on the left hand side of the phpmyadmin page.
5. Click on the json database.
You will see a page which states no tables exists on database json.
Click the SQL tab and paste the following table definition in. Then click go
CREATE TABLE `users` ( `id` int(10) unsigned NOT NULL auto_increment, `userid` varchar(14) NOT NULL, `firstname` varchar(20) NOT NULL, `lastname` varchar(20) NOT NULL, `email` varchar(127) NOT NULL, PRIMARY KEY (`id`), KEY `userid` (`userid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
You should receive a message that your query took x seconds back. Now in the sidebar of phpmyadmin you will see your users table.
If you click on it you will see a list of 5 fields and their definition.
6. Now lets add some dummy data to our table.
Once again click on the sql tab and paste the following 5 lines
INSERT INTO `users` VALUES(1, 'fhardy', 'Frank', 'Hardy', 'fhardy@hauntedclock.com'); INSERT INTO `users` VALUES(2, 'jhardy', 'Joe', 'Hardy', 'jhardy@hauntedclock.com'); INSERT INTO `users` VALUES(3, 'ndrew', 'Nancy', 'Drew', 'ndrew@hauntedclock.com'); INSERT INTO `users` VALUES(4, 'sdoo', 'Scooby', 'Doo', 'sdoo@mysterymachine.com');
Click Go.
The users table will now contain 5 rows.
3. Create PHP JSON Page
1. As of php 5.2 json creation is built in. It is beyond the scope of this article to cover the basics of connecting to a php database but the code is fairly self explanatory. Create a new php file named jsontest.php in your htdocs directory with the following contents.
<?php // Database credentials $host = 'localhost'; $db = 'json'; $uid = 'json'; $pwd = 'json1';
// Connect to the database server $link = mysql_connect($host, $uid, $pwd) or die("Could not connect"); //select the json database mysql_select_db($db) or die("Could not select database"); // Create an array to hold our results $arr = array(); //Execute the query $rs = mysql_query("SELECT id,userid,firstname,lastname,email FROM users"); // Add the rows to the array while($obj = mysql_fetch_object($rs)) { $arr[] = $obj; } return the json result. The string users is just a name for the container object. Can be set anything. echo '{"users":'.json_encode($arr).'}';
?>
2. Test the page with the following URL http://localhost:8888/jsontest.php Note if you changed your port from the MAMP default, change it in this URL as well. In essence the port should be set to the same port as what appears in the MAMP home page address You should see a page with output similar to the following.
{"users":[{"id":"1","userid":"fhardy","firstname":"Frank","lastname":"Hardy","email":"fhardy@hauntedclock.com"}, {"id":"2","userid":"jhardy","firstname":"Joe","lastname":"Hardy","email":"jhardy@hauntedclock.com"}, {"id":"3","userid":"ndrew","firstname":"Nancy","lastname":"Drew","email":"ndrew@hauntedclock.com"}, {"id":"4","userid":"sdoo","firstname":"Scooby","lastname":"Doo","email":"sdoo@mysterymachine.com"}]}
4. Finally the iPhone portion
Phew... still with me? Here comes the payoff.
1. Download TouchJSON - The library TouchJSON provides a very simple json to objective c translation library. Download the JSON Touch library from this link (http://code.google.com/p/touchcode/downloads/list).
2. Uncompess the library and you will see a file tree with the following.
3. Create a new View Based Project called JsonTest
4. Create a new Group call JsonTouch
Drag the contents of the TouchJSON Source directory (created in step 2) from the downloaded tree into the JsonTouch group and tell XCode to copy the files into your project.
Your Project Hierarchy should look like this.
5. In JsonTestViewController.h add the <UITableViewDelegate,UITableViewDataSource> protocol declarations to your interface line
@interface JsonTestViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> {
6. In In JsonTestViewController.h add the following instance variables and property lines.
UITableView *tableview; NSArray *rows;
@property (nonatomic,retain) IBOutlet UITableView *tableview; @property (retain,nonatomic) NSArray *rows;
When you are done the header file should look like the following
#import <UIKit/UIKit.h>
@interface JsonTestViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> { UITableView *tableview; NSArray *rows; } @property (nonatomic,retain) IBOutlet UITableView *tableview; @property (retain,nonatomic) NSArray *rows; @end
Save your changes
7. In JsonTestViewController.m create the viewDidLoad method.
- (void)viewDidLoad { [super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://localhost:8888/jsontest.php"]; // Modify this to match your url. NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL NSLog(jsonreturn); // Look at the console and you can see what the restults are NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding]; NSError *error = nil; // In "real" code you should surround this with try and catch NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error]; if (dict) { rows = [[dict objectForKey:@"users"] retain]; }NSLog(@"Array: %@",rows); [jsonreturn release]; }In a nutshell this code
a) Creates a url which points to your php path.
b) Initializes a string with the return value from that URL
c) Creates an NSData object from that return
d) Creates a dictionary using the Json Touch Deserializer. The format of this dictionary is users->[array of dictionaries 1 per row]
e) Populates an array from the dictionary. This array will feed our tableview.
8. Create the 2 required methods to display a table
// Return the number of entries in the array this is the number of rows in our table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [rows count]; }
// Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } // Configure the cell. NSDictionary *dict = [rows objectAtIndex: indexPath.row]; cell.textLabel.text = [dict objectForKey:@"userid"]; cell.detailTextLabel.text = [dict objectForKey:@"email"]; return cell; }
9. In JsonTestViewController.m add the import statement for the TouchJson library at the top of the file.
#import "CJSONDeserializer.h"
10. Open the file JsonTestViewController.xib in Interface Builder. Add a tableview to the view. Connect the datasource, and delegate methods to the FileOwner. Connect the referencing outlet (of the tableview) to the tableview property.
Make sure MAMP is running, then run the app in the simulator. The results will look like the following.
Conclusion
This is a very simple example of a really powerful technique. The JSONTouch library and the iPhone sdk make it trivial to consume JSON resources from any source. If you use the library, please contribute to the folks over at TouchCode. I hope you have enjoyed this article, and if you have any questions I can be reached at rdominelli@tempered.mobi.
Project Source Code: JSonArticle.zip