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
Credit photo: Svilen Milev
·






[...] This post was mentioned on Twitter by yabulka, Marin Todorov. Marin Todorov said: #touchcodemagazine Tutorial: Fetch and parse JSON http://goo.gl/fb/UF0fy [...]
Amazing tutorial with deep details on how to fetch and parse JSON, Thanks a lot!
The application is helpful in understanding about the consumption of json service.May i know how has the web service for the same been created? I wanted to know the step by step procedure to create the webservice with output in JSON format.Please share the server side code if possible.
The JSON being read in the tutorial comes from http://www.kiva.org – a non-profit organization helping entrepreneurs from around the world, I doubt they’ll provide you with their source codes
However I’m sure that you can find good code examples via simple search in Google
May i know how to get the HTTP response code from header? Code such as 202,404..
Thanks in advance.
Hey Jonh,
I’m not sure if you can get the headers using the common network connection class. Basically if you get any kind of error – (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error will be called and you have the chance to read what’s in the “error” parameter, otherwise you can count that everything is just fine and file is downloading successfully
If you are looking for more advanced library to deal with http requests search in google for “asihttprequest” – it’s an extremely good one
Thanks a lot Marin.
Hi, i am using Xcode 4 with ARC. it gives me error when i compile the project, despite all the release/autorelease/retain issues, I had another issue which I cant find an answer not even in the apple developer site.
1. Error message: “Cast of Objective-C pointer type ‘NSMutableString *’ to C pointer type ‘CFMutableStringRef’ (aka ‘struct __CFString *’) requires a bridged cast:”
On statement:
CFStringAppendCharacters((CFMutableStringRef)json, &uc, 1);
2. Error message: “Cast of Objective-C pointer type ‘NSMutableString *’ to C pointer type ‘CFMutableStringRef’ (aka ‘struct __CFString *’) requires a bridged cast”
On statement:
CFStringAppendCharacters((CFMutableStringRef)*o, &uc, 1);
I checked on the official developer site and it was said that the CFMutableString and NSMutableString is toll-free bridging. Instead in compile time it gives me errors. I tried as xcode recommended casting them using __bridge to convert directly. However, this gives me EXC_BAD_ACCESS error.
Can anyone help me with this? Thanks in advance.
MacKitty
Hey – I think instead of trying to fix the JSON framework you can do 2 things :
1) if your app is iOS5 only – use the new native JSON classes, I’ve written a chapter about it in my latest book and you can find exactly the JSON part for free here: http://www.raywenderlich.com/5492/working-with-json-in-ios-5
2) if you are after 4.x compatibility just turn off ARC for the JSON library: go to your target’s settings, open build phases, open up Compile sources, select all files you want to turn off ARC for, press Enter, in the popup window enter “-fno-objc-arc”, restart Xcode and load up your project
HEllo thanks for the amazing tutorial i really learned a lot
i want to know that when i tap the button Start in the application it will only gets the data at the zeroth index of the parsed array.
I know it because of
NSDictionary* loan = [latestLoans objectAtIndex:0];
but i need to know how to get data consecutively.thanks for the help
hey, you need to iterate over the “latestLoans” array – it’s basic Objective-C … if you have difficulties with that I recommend taking the “iOS Apprentice” class here : http://touch-code-magazine.com/iOS5ByTutorials
yes that was my first guess
i did this
for (int i = 0; i<[latestLoans count]; i++) {
NSDictionary* loan = [latestLoans objectAtIndex:i];
//choose a random loan
NSLog(@"%@",loan);
//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];
NSLog(@"label is —–%@",label.text);
but whenever i hit the start button the loadData is called all the time and i keep getting the same value from the jason
may b i should have to implement a NEXT button and try it there
Hey,
I was looking for something like what you explained. I’ve downloaded your code and really appreciate what you’ve shared. We need to use iPad as graphical console for a network device that its API uses JSON for communication. So you article is a great boost for us. Thank you very much.
amir.
This really was a great tutorial. Thank you so much
Great work! Thank you very much!
Hello Guys,
This is Great work. but if i developing same application then it fire error. can you please help me on that what is the error ?
2012-07-21 04:57:54.282 ThisisFirstApp[776:fb03] Exception: -[__NSCFString JSONValue]: unrecognized selector sent to instance 0x73aaa00
[...] Fetch and parse JSON [...]
[...] Fetch and parse JSON [...]
[...] of the more popular articles on Touch Code Magazine is the “Tutorial: Fetch and parse JSON“. However I wrote this tutorial quite some time ago, so now I decided to re-write it so that it [...]
[...] of the more popular articles on Touch Code Magazine is the “Tutorial: Fetch and parse JSON“. However I wrote this tutorial quite some time ago, so now I decided to re-write it so that [...]
thank for giving such a wonderfull example with project but i want to know that how to read data from downloaded Json file.
Thank You
In exactly the same way – but instead of getting the nsdata from Internet, you should load the local file.
hi marin!
I have a big problem..
in my json database are some names and urls and I have to load one url into my webview!
i hope you can help me!
nice tutorial…clear xplanation ….
Thank you…