Sunday, July 8, 2012

iPhone, JSON and Flickr Tutorial – Part 2

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (NSString *)stringWithUrl:(NSURL *)url
{
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:30];
// Fetch the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
 
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
 
// Construct a String around the Data from the response
return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
}
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 …
1
2
3
4
5
6
7
8
- (id) objectWithUrl:(NSURL *)url
{
SBJSON *jsonParser = [SBJSON new];
NSString *jsonString = [self stringWithUrl:url];
 
// Parse the JSON into an Object
return [jsonParser objectWithString:jsonString error:NULL];
}
NOTE: The method above returns id because the actual object type can vary between anNSDictionary 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
"title" : "Jaiku | Latest Public Jaikus",
"url": "http:\/\/jaiku.com",
"stream": [
{
"id": "47163562",
"title": "Lol....nope",
"content": "",
"icon": "http:\/\/jaiku.com\/images\/icons\/jaiku-sms.gif",
"url": "http:\/\/vicious00013.jaiku.com\/presence\/47163562",
"created_at": "2008-10-20T18:22:50 GMT",
"created_at_relative": "1 minute ago",
"comments": "0",
"user":
{
"avatar": "http:\/\/jaiku.com\/image\/4\/avatar_52304_t.jpg",
"first_name": "Ronnie",
"last_name": "Beckett",
"nick": "vicious00013",
"url": "http:\/\/vicious00013.jaiku.com"
}
},
{
"id": "47163407",
"title": "Nice, so HP refuses to (or can't) sell us the drive carriers for their servers.",
"content": "",
"icon": "",
"url": "http:\/\/randomfrequency.jaiku.com\/presence\/47163407",
"created_at": "2008-10-20T18:21:16 GMT",
"created_at_relative": "3 minutes ago",
"comments": "3",
"user":
{
"avatar": "http:\/\/jaiku.com\/image\/36\/avatar_47586_t.jpg",
"first_name": "Vincent",
"last_name": "Janelle",
"nick": "randomfrequency",
"url": "http:\/\/randomfrequency.jaiku.com"
}
} ]
}
Here is an how we would use the above methods to download the public feed from Jaiku and cast it to an NSDictionary …
1
2
3
4
5
6
7
- (NSDictionary *) downloadPublicJaikuFeed 
{
id response = [self objectWithUrl:[NSURL URLWithString:@"http://jaiku.com/feed/json"]];
 
NSDictionary *feed = (NSDictionary *)response;
return feed;
}
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:
1
2
NSDictionary *feed = [self downloadPublicJaikuFeed];
NSLog(@"Here is the title of the feed: %@", [feed valueForKey:@"title"]);
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…
1
2
3
4
5
6
7
8
9
10
11
12
NSDictionary *feed = [self downloadPublicJaikuFeed];
 
// get the array of "stream" from the feed and cast to NSArray
NSArray *streams = (NSArray *)[feed valueForKey:@"stream"];
 
// loop over all the stream objects and print their titles
int ndx;
NSDictionary *stream;
for (ndx = 0; ndx < stream.count; ndx++) {
NSDictionary *stream = (NSDictionary *)[streams objectAtIndex:ndx];
NSLog(@"This is the title of a stream: %@", [stream valueForKey:@"title"]);
}
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!
NOTE: For those that are interested, there are many handy ways to convert XML into JSON on the server side. To find out more, take a look at the official JSON.org website. I’ve used the Java JSON library to convert XML feeds into JSON more times than I can count!

No comments:

Post a Comment