JSON Framework for iPhone (Part 2)

Editor’s Note: Due to the popularity of this iPhone JSON series, a new three part tutorial series on working with JSON was published in August 2009. You can find the latest JSON iPhone tutorial series at the links below:

  1. iPhone JSON and Flickr Tutorial – Part 1
  2. iPhone JSON and Flickr Tutorial – Part 2
  3. iPhone JSON and Flickr Tutorial – Part 3

In part 1 we shared with you how to download, install and configure an iPhone project to use a JSON framework developed by sbrautaset. In today’s post I will share with you how to use the framework to download and parse a JSON feed. As you will see it is much easier to deal with JSON within an iPhone application than to have to deal with XML.

JSON is most commonly used as an alternative to XML for RESTful style web services. As such any example that demonstrates anything about JSON must first begin with an example of how to download JSON data.

Let’s begin by creating a method called stringWithUrl: that will download data from a specified URL and return the data as an NSString

Now that we have the ability to download the JSON data as a string we are ready to parse the string into an object we can use. What is wonderful about this particular JSON framework is that it can parse JSON into a collection of NSDictionary and NSArray objects which are amazingly simple to deal with.

Combined with the stringWithUrl: method above, we are now ready to use the JSON framework to create another method that will parse the JSON string into an Object …

NOTE: The method above returns id because the actual object type can vary between an NSDictionary and an NSArray.

Now let’s put this to use! First, consider a real example of a JSON feed. Here is a sample of what a public feed from Jaiku looks like:

Here is an how we would use the above methods to download the public feed from Jaiku and cast it to an NSDictionary

At this point we have everything we need to query any aspect of the feed. For example here is how you might query the “title” field:

Notice in the sample Jaiku feed there is a value “stream” that is actually a list of objects. This is an example of how an NSArray is created to contain a list of object in JSON. Although the JSON frameworks creates the array, you will still need to cast it from a generic ‘id’ type into an NSArray before you can use it safely. Here is an example of how we would query the array of objects and handle each object in the array…

Conclusions

As you can see, working with JSON feeds are much simpler than XML feeds. There is no cumbersome parser you have to create; and getting values from the JSON object is as simple as working with an NSDictionary or NSArray. If only more Web Service APIs used JSON the world would be a better place!

42 Comments

  1. Thanks for this post. I was JUST looking for info on how to communicate with my ruby/rails backend. This is perfect.

    • yup, thanks for providing those needs with a perfect example easy to understand even for the begineers

  2. Thanks for the great tutorial.

    But there is one issue. I am not sure, but I think you create a memory leak with

    “return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];”
    and
    “SBJSON *jsonParser = [SBJSON new];”

    because these objects are not released.

  3. I’m trying to use the Json Framework and I’m getting this when I compile after setting the following options up:

    >Copy the content of the ‘SDKs’ folder to ~/Library/SDKs. (You may have
    >to create that directory.)

    >To make use of this SDK, select your target in the left-hand menu and
    >click the blue Info button (Apple-i). Add the following new line to
    >the “Additional SDKs” option: “$HOME/Library/SDKs/JSON/$(PLATFORM_NAME).sdk”.
    >Finally you have to add the entry ‘-ObjC -ljson’ to the “Other Linker
    >Flags” option.

    error: There is no SDK with specified name or path ‘/Users/mini/Library/SDKs/JSON/macosx.sdk’

    Is there something I didn’t wrong?

  4. Great article and thanks for the tutorial, just a side note, the last code snippet has an error. Rather than:

    for (ndx = 0; ndx < stream.count; ndx++)

    the ‘stream’, should be ‘streams’.

    for (ndx = 0; ndx < streams.count; ndx++)

  5. @Pete

    There are only the four steps outline in part one that you need to follow. I’ve just now repeated the steps in a new project to verify and it continues to work for me. Are you sure you didn’t leave out any of the steps? Here is a quick recap …

    1. Download the DMG http://json-framework.googlecode.com/files/JSON_2.1.1.dmg
    2. Mount the DMG and copy the directory /Volumes/JSON_2.1.1/SDKs/JSON to ~/Library/SDKs/JSON
    3. Now, in the build properties (for both Debug and Release) there are two additional properties to configure (omit the double quotes bellow) …
    3.a “Additional SDKs” must be set to “$HOME/Library/SDKs/JSON/$(PLATFORM_NAME).sdk”
    3.b “Other Linker Flags” must be set to “-ObjC -ljson”
    4. In the source file that uses the JSON library, add the following import “#import <JSON/JSON.h>”

    That should do the trick.

  6. I can’t seem to get it to work with the instructions in the INSTALL file on the DMG or with yours, but if I fall back on my Cocoa experience I can drag the libjson.a file into my project IDE and also drag the SBJSON.h, NSObject+SBJSON.h, NSString+SBJSON.h in my project and import the files via a “” local import verses a system import. Everything links and works. Is there some special project setting that is used for .sdk bundles? My .sdks actually look like folders not some bundle icon which hides the internal structure from casual users. Is that correct? Or is there a special chmod setting that needs to be set for these .sdks?

    #import “SBJSON.h”
    #import “NSObject+SBJSON.h”
    #import “NSString+SBJSON.h”

  7. it was really nice tutorial. In my case I have a sub object under the main object. how do I access sub objects or sub arrays after I get every ting from the server on my NSDictionary?

    tanks

  8. @nex Getting another JSON object is simple. Use the key to get the object from the NSDictionary and then cast it into a NSDictionary … this is also the method for getting at NSArrray values.

  9. Great article!
    The NSDictionary *stream; before the for loop gives warning.I guess it is not required.

  10. Thanks Pete
    your instruction worked for. i was unable to configure JSON on my MAC mini running 10.5.6 and iphone OS 2.2.1 but when just drag JSON folder and libjson.a in my project it works fine.

    Thanks

  11. I have spent a lot time to complile the code.
    Reason was uninitialized variables ‘response’ and ‘error’

    NSURLResponse *response;
    NSError *error;

    // Make synchronous request
    urlData = [NSURLConnection sendSynchronousRequest:urlRequest
    returningResponse:&response
    error:&error];

    Better to to the initialized:

    NSURLResponse **response = nil;
    NSError **error = nil;

    Thanks for article!

    Mikhail.

  12. Great tutoral! Thanks. Do I need to make a NSMutableData *response global to hold the response. I’m getting null for [feed valueForKey:@"title"] using the Jaiku example output. Thanks.

  13. Does anyone know if this counts as using a 3rd party API/framework which may mean it is rejected by the iphone app store?

  14. @Chris,

    Use of this API will not result in rejection. I have used it within my own application that was accepted and put into the store.

    – Rodney

  15. Still a good article for starting out.

    One questions I am working with: how to send a JSON string to the URL, for example using an RPC type call to my php files on the server.

    John

  16. Hello

    It’s ok to deserialize to a dictionary.

    But what about to deserialize as objects?

    For example I have a book class both in server-side and iphone-side

    I want to deserialize the serialized book object of server side to a book object in iphone?

    Is it possible?

  17. Am I wrong, or shouldn’t you be autoreleasing the return value of stringWithUrl:url (first code fragment) to avoid a memory leak??

    Oh another commenter (Lars) noticed the same thing. I think you do need to autorelease.

    Haven’t compiled this, but something like:

    NSString *ret = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
    return([ret autorelease]);

    See p.168 of _Learn Objective-C on the Mac_.

  18. Great post, thanks!
    I am also trying to figure out how to send (POST) JSON data to a RESTful web service. I did not find a possibility to configure the HTTP method for the NSURLRequest object.

    Any idea?

    Thanks
    Guido

  19. Hey, just figured I’d mention it in case people aren’t HTML savvy – your [code] tag, or whatever formats your code is parsing ampersands, angle brackets, etc as their html elements. &amp, etc.

  20. Thanks for making the tutorial, I really want to understand it properly, but I’m coming up with errors straight away.

    The new version of JSON is 2.3, and this requires #import “JSON.h”, not #import <JSON/JSON.h, I figured that out!
    After simply copying your code and trying to compile to test, I get the error message SBJSON not declared, there's no class SBJSON, just NSObject+SBJSON. In the installation instructions for the new SBJSON2.3 it doesn't say anything about changing the build properties, do i still need to do this?

    I changed SBJSON to SBJsonParser, but now it's saying amp is undeclared, where am I meant to declare amp, and what is it??

    any help appreciated!

    Mike

  21. Mike,

    Try this:

    SBJsonParser *parser = [[SBJsonParser new] autorelease];
    NSDictionary *results = [parser objectWithString:jsonString error:nil];
    NSLog(@”%@”, results);

    Tbone

  22. Though you don’t know me, you now have my eternal gratitude for this wonderful article.
    Bless you.
    Much Obliged.

  23. Im working on a similar project. Im using NSURLConnection to POST data to a php file which i know works because ive tested it with an html POST form manually.

    Im having the iOS app post this code:

    + (NSArray *)fetchTimelineForUDID:(NSString *)udid{

    NSData *postData = [udid dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    NSLog(@”%@”,postData);
    NSString *postLength = [NSString stringWithFormat:@”%d”, [postData length]];
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@”http://www.santiapps.com/iGlobe/readtags2.php”]];
    [request setURL:url];
    [request setHTTPMethod:@”POST”];
    [request setValue:postLength forHTTPHeaderField:@”Content-Length”];
    [request setValue:@”application/x-www-form-urlencoded” forHTTPHeaderField:@”Content-Type”];
    [request setHTTPBody:postData];
    NSURLResponse *response;
    NSError *error;
    NSData *urlData = [NSURLConnection sendSynchronousRequest:request
    returningResponse:&response
    error:&error];
    return nil;
    }

    at the moment i return nil just to test out NSLogs….but the thing is the NSURLConnection returns NSData. What im expected to return from this function is an NSArray. How can i make that conversion if thats what needs to be done?

  24. ok, does that url passed to the stringWithUrl method have to be in the format

    GET
    http://www……/read.php?var1=value [so u can fetch records where id=value]

    or can it be

    POST
    http://www…./read.php [where the data is in the HTTPbody?]

    I cant get the 2nd one to work.

  25. Thanks for a very good tutorial, it helped me a lot !
    Initially even I was getting the same error that “Mike” was getting.
    I hadn’t read the entire article…(I mean the replys and all)

    But with my programming experience I learned that instead of creating an SBJSON,
    one needs to crate SBJsonParser ‘s object.
    As SBJsonParser ‘s objects would respond to / call the parser method !!

  26. Thank you thank you! i was so stuck on my 2nd level of json. your for loop fixed my problem. thanks man!

  27. Really was a good post and help a lot….

  28. Thanks for your valuable tutorial.i think anyone can understand this JSON Concept clearly and easily.It helped me a lot.

  29. I am new in Objective C and Frameworks. This tutorial helps me a lot to understand JSON Framework.

    Thank You.

Comments are closed.