iOS: Wunderground JSON calling and parsing

While attending WWDC 12 one of the Apple engineers made a comment as his presentation started about how nearly half of all applications in the App Store load and parse JSON. He was half-joking, but there must be some truth to that. Most application authors need to consume someone else’s data in interesting and unique ways to form the backbone of their app. So this morning I decided to give it a spin myself, using the weather data APIs from Wunderground (documentation link). After reading up on their documentation, it looked quite solid and quite easy to understand.

In the past I’ve used some third-party JSON libraries to parse it – but now iOS 5+ has JSON parsing built into Foundation. I had forgotten about that – but it’s a welcome addition. I wish we had it earlier, but whatever.

Sign up for a developer key with Wunderground. If you can get JSON weather data, or any data for that matter, this little post should help you out if you need some. With Wunderground they have some tiered API access – ranging from pretty restricted but free to wide open hit that server a ton for a bunch of money. I’m floating on the free but limited to 10 hits per minute account (for now). If I decide to take anything to the App Store using it, I’d have to buck up potentially depending on the popularity of the app. Realistically I could probably keep the free account :)

Once you have your key, you’re able to make an HTTP call and return all kinds of useful data. Take a look at the documentation again and look at the Request URL format. Tons of things are possible there. For instance a call to return conditions for 01701 (Framingham in Boston):

http://api.wunderground.com/api/<developer_key>/conditions/forecast/q/01701.json

That’s it. You could use Location services on iOS to use latitude and longitude instead, use an airport code, automatic IP address, etc. What does the JSON look like when it comes back (say in a browser to check)? Like this (abbreviated):

{
    "response": {
        "version": "0.1"
         ,"termsofService": "http://www.wunderground.com/weather/api/d/terms.html"
         ,"features": {
         "conditions": 1
	,
	"forecast": 1
	}
    }
		,	"current_observation": {
		"image": {
		"url":"http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png",
		"title":"Weather Underground",
		"link":"http://www.wunderground.com"
		},
		"display_location": {
		"full":"Framingham, MA",
		"city":"Framingham",
		"state":"MA",
		"state_name":"Massachusetts",...

I stopped where the ellipses are above. When you try this yourself you can see the entire information block and print that out so you understand the structure of the JSON. This is what I’ve done in order to process what I want out of the data returned from my calls. It’s an important step to do on your own. See what results you’re getting and test your request in a browser first.

So how do you go about calling and getting the data from within an iOS application? It’s actually really straightforward:

//Define an NSMutableData object in your header (mine is called responseData).

NSURLRequest *theRequest = [NSURLRequest requestWithURL:
             [NSURL URLWithString:@"http://api.wunderground.com/api/<DEVKEY>/conditions/forecast/q/01701.json"]];
NSURLConnection *theConnection=[[NSURLConnection alloc] 
                initWithRequest:theRequest delegate:self];
if(theConnection){
    responseData = [[NSMutableData alloc] init];
} else {
    NSLog(@"failed");
}

That’s the call. Insert your own DEVKEY and query for yourself. So that makes the call – what about getting the data? When you set the delegate to self, there are methods you can add which will be called – you’ll need to add those.

#pragma mark - Delegates for Weather Data

- (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
{   
    NSString *msg = [NSString stringWithFormat:@"Failed: %@", [error description]];
    NSLog(@"%@",msg);
}

//All the data was loaded, let's see what we've got...
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    NSError *myError = nil;
    NSDictionary *res = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves  error:&myError];
    NSArray *results =  [res objectForKey:@"current_observation"];
    NSArray *cur = [results valueForKey:@"weather"];
    NSArray *tmp = [results valueForKey:@"temp_f"];
    NSLog(@"Current conditions: %@, %@º", cur, tmp);
}

You’ve pulled out some useful data! Now seeing how you pulled that out, you should be well on your way in pulling out all kinds of other stuff you might need. And without a third-party JSON solution.

Related Posts Plugin for WordPress, Blogger...

8 thoughts on “iOS: Wunderground JSON calling and parsing

  1. Brian

    I was wondering if you could post the full example. I’m new to iOS so I’m still not sure how all the pieces fit in here with your example. Thanks

    Reply
    1. Eric Post author

      If you compare the JSON returned and print it out – you can see how the data is formatted. I’ve given you an example in how to pull information out of the returned JSON blob. If you’d like to see how to get at every piece of that data, you’re probably wanting to Google for JSON parsing in general. You might be able to figure things out looking at the JSON and the connectionDidFInishLoading method and see what I’ve already supplied and then try to pull out choice pieces on your own there. Have you been able to return JSON at all yet.

      Reply
  2. Jorgen

    I was testing this in an app but the result is — Current conditions: (null), (null)º —
    Any idea? I’m feeding long,lat instead of an airport code.

    Reply
  3. Daniel Sadjadian

    Hi,

    First of all, this is a superb post! Thank you so much, I found this very useful indeed and it worked like a charm.

    I just have one question, I have set up a simple function in my iOS app and basically it return the co-ordinates of the devices current location. Now does the Wunderground API support getting weather information by sending it co-ordinates rather than a specific place name? And if so, how can I modify the URL to do this?

    Thanks,
    Dan

    Reply
  4. Frank

    Thank you sooooo much, when I did this for android I had to parse the text and make List arrays, I just couldn’t figure out how get it to work, and every other tutorial is Twitter, twitter, twitter ENOUGH OF THE TWITTER POSTS! I got twitter to work, but it didn’t seem to be the same layout. Thanks again, now I’ve got about 20 new apps to make for IOS!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


three × = 24

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>