Monday, 10 September 2012

Fetch and parse JSON in iPhone


Tutorial: Fetch and parse JSON


Today I’ll show you how to how to build a simple iPhone application which loads JSON data from the Internet and reads some texts and such to use within its UI.

Thanks to Stig Brautaset loading JSON encoded data from the Internet is quite easy. You can head to github and have a look at the latest version for download : https://github.com/stig/json-framework or you can just download the project for this tutorial: json_demo1 where JSON is already included.


Create a new View based project in XCode and call it “json_demo” (or as I mentioned just open the already downloaded project json_demo1).
First copy the classes from the JSON library (it’s always good to put such classes in a group called Externals or Library or whatever you want)







Now in your XIB file you need to add a label and a button. When the user hits the button the app will start loading the JSON from Internet and when all data is received it’ll show the information. In this example I’m using JSON from Kiva.org – the guys at Kiva are helping developing countries entrepreneurs get their loans funded – it’s an interesting concept have a look at this later on.
Since Kiva’s JSON is a list of loans, the app will just get the latest incoming loan and will show who needs it and how much from the loan is left to be funded by the Kiva users. (btw this is real code from a project I’m working on right now)
So lay down your UI to look anything like this:

                                        


Now in “json_demo1ViewController.h” change your interface definition like that:
@interface json_demo1ViewController : UIViewController {
 IBOutlet UILabel* label;
 
 NSMutableData* responseData;
}
 
@property (retain, nonatomic) NSMutableData* responseData;
 
-(IBAction)loadData;
 
@end
There’s an outlet for the label and IBAction for the Button – nothing you shouldn’t know how to do. The extra is the definition of the NSMutableData property – we’ll need this one to gather the incoming data from the internet request.
In “json_demo1ViewController.m” just after the implementation line add :
@synthesize responseData;
Now go back to Interface Builder and connect the label to the label IBOutlet and the button to the loadData IBAction.
The UI is now finished and we’ll look how to load and parse JSON data.
First add on top of the implementation file of the controller an import :


#import "JSON.h"
#define kLatestKivaLoansURL @"http://api.kivaws.org/v1/loans/search.json?status=fundraising"
The define sets the URL with the JSON of the latest Kiva.org loans
Then add the implementation of the IBAction of the button:
-(void)loadData
{
 self.responseData = [NSMutableData data];
 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kLatestKivaLoansURL]];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
In loadData responseData is emptied and prepare to receive the incoming data bits. A URL request is made out of the NSString with the URL.
The most important line is the one initializing the NSURLConnection – the connection is initialized with the prepared request and the UIViewController sets itself as the delegate for the connection – this way the controller connects to the connection class and can handle the events of incoming data, errors, etc.
Let’s handle few of the connection events:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [responseData setLength:0];
}
 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [responseData appendData:data];
}
 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
 [connection release];
 self.responseData = nil;
}
didReceive response means the headers of the response are received and data starts poring in – that’s a good place to do some preparations – in the case above just set Length to 0 bytes. didReceiveData event happens more than once (unlike all other in this example) – this method will be called every time a chunk of data arrives – this method is a good place to update download progress bars and such, as saving the incoming data. didFailWithError of course means the request failed – read the error parameter for more info.
When all the connection response has been read connection calls the “connectionDidFinishLoading:” method of the delegate and that’s the last you’ll hear from the connection. In this method do all your processing of the data as it’s already fully downloaded:
#pragma mark -
#pragma mark Process loan data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [connection release];
 
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
 self.responseData = nil;
 
 NSArray* latestLoans = [(NSDictionary*)[responseString JSONValue] objectForKey:@"loans"];
 [responseString release];
 
 //get latest loan
 NSDictionary* loan = [latestLoans objectAtIndex:0];
 
 //fetch the data
 NSNumber* fundedAmount = [loan objectForKey:@"funded_amount"];
 NSNumber* loanAmount = [loan objectForKey:@"loan_amount"];
 float outstandingAmount = [loanAmount floatValue] - [fundedAmount floatValue];
 
 NSString* name = [loan objectForKey:@"name"];
 NSString* country = [(NSDictionary*)[loan objectForKey:@"location"] objectForKey:@"country"];
 
 //set the text to the label
 label.text = [NSString stringWithFormat:@"Latest loan: %@ from %@ needs another $%.2f, please help",
       name,country,outstandingAmount
       ];
}
If you go trough the code it’s quite simple. First the received data is turned into text by : [[NSString alloc] initWithData: encoding:] and then this text is parsed into an NSArray. The JSON library adds a JSONValue method to NSString, so when you call it you get back an object representing the JSON structure. In the Kiva case loans is a root property and contains a list of objects, so in the end in latestLoans we get an NSArray with the list of loans.
NSArray* latestLoans = [(NSDictionary*)[responseString JSONValue] objectForKey:@"loans"];
Parsing the data further is a matter of drilling trough arrays and dictionaries, but thanks to JSON.h all the parsing was done in between everything else by calling JSONValue on the string having the json text.
Now running the application will show you the information about the latest Kiva.org loan to be funded:



Thanks for reading, once more here is the link to the demo project : json_demo1
Looking forward to your feedback






No comments:

Post a Comment