Whenever I clone a repo from Github I'm used to being able to use git pull and git push on their own to pull and push from origin and to master respectively.

When I set up my own git repo outside of Github, I wondered why these didn't work out of the box. Executing those commands would give me an error saying Git doesn't know which branch to merge with...

It turns out you can set up your preferred remote and local branches to pull and push to and from. Just edit the config file inside the .git/ directory in your local repo.

You may find that if you added a remote repo previous the [remote] section will already be present.

[branch "master"]
        remote = origin
        merge = refs/heads/master

[remote "origin"]
        url = url/to/my/gitrepo.git
        fetch = +refs/heads/*:refs/remotes/origin/*

I've recently started favouring Git instead of SVN for my newer projects and one of the things I do religiously is tagging.

Tagging in Git is very easy and simple, but I ran into a small problem. I created a tag and named it incorrectly and pushed it to my remote repo before I noticed the mistake. So I deleted the tag and created a new one with the correct name and pushed it. Then I did a pull to ensure I was completely synced with the remote repo and it pulled down my old tag that I just deleted...

It turns out that in order to delete a remote tag you need to do the following (replace 'MyTag' with the name you gave your tag):

git tag -d MyTag
git push origin :refs/tags/MyTag

So the previous post focussed on retrieving data from a webservice - namely Google's Local Search.

This post will focus on parsing the JSON returned from the webservice.

My personal choice for parsing JSON is the SBJON library. There are others out there such as TouchJSON and YAJL so check them put and decide for yourself.

Let's start with a quick recap on what JSON is and how it can be used.

Wikipedia says:

JSON (an acronym for JavaScript Object Notation) is a lightweight text-based open standard designed for human-readable data interchange. It is derived from the JavaScript programming language for representing simple data structures and associative arrays, called objects. Despite its relationship to JavaScript, it is language-independent, with parsers available for virtually every programming language.

JSON presents its data as key-value pairs. Each value is referenced by a key name, which is a string. If you were to represent a person in JSON, their name would be referenced by the key "name" like so: "name" : "James".

So, JSON represents data in a way that can be passed between applications easily. Perfect.

So when parsing data from a webservice, the first thing you should do is figure out your model. Look at an example of the webservice's response and figure out which bits represent objects, arrays of objects, fields that belong to an object, etc.

But what kinds of data can JSON represent?

Objects are everything between the braces ( { } ). Strings are enclosed in quotes. Numbers aren't enclosed by anything and just appear as numbers, e.g. 12345. Arrays are enclosed in square brackets ( [ ] ). Booleans take the form of the words 'true' or 'false' (without quotes). Null values are represented as 'null' (without quotes).

So an example of JSON using all these data types:

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": 
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber": 
     [
         {
           "type": "home",
           "number": "212 555-1234"
         },
         {
           "type": "fax",
           "number": "646 555-4567"
         }
     ]
 }

And it's representation in Objective-C:

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    NSString *firstName;
    NSString *lastName;

    NSInteger age;

    NSDictionary *address;

    NSArray *phoneNumbers;
}

@end

You may think we've missed out some information, such as the details of the address, and phone numbers. It's you decision how you model your objects. I've chosen to store the address details in a dictionary, each value being referenced by a key name, just as it is in JSON. The phone numbers also stored in dictionaries, but then those dictionaries put into an array.

If you wanted to, you could create another Class named Address and use it to store the address details. This may be a more object-oriented approach and useful if addresses are used in other places throughout your application without needing to be tied to a Person.

So now that you have your object model, you need to get the data out of the JSON and create instances of your model.

SBJSON has a useful SBJsonParser class that can parse an entire JSON object in one line:

SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObjects = [jsonParser objectWithString:jsonString error:&error];
[jsonParser release], jsonParser = nil;

SBJSON treats JSON objects as dictionaries in Objective-C. Depending on the webservice you may get a JSON object as the top level object or you may get an array. For this reason, objectWithString:error: has id as it's return type. You can use Objective-C's dynamism to determine which type of data store the parser as returned, like this:

id jsonObject = [jsonParser objectWithString:jsonString error:&error];

if ([jsonObject isKindOfClass:[NSDictionary class]])
    // treat as a dictionary, or reassign to a dictionary ivar
else if ([jsonObject isKindOfClass:[NSArray class]])
    // treat as an array or reassign to an array ivar.

If the webservice only ever returns one of the two representations as it's top level then you can go ahead and assume it will be either an Array or Dictionary, and not have to worry about checking.

Now you have your JSON data in a format that you can manage via Objective-C. All you need to do now is iterate over the contents of the dictionary/array and create instances of Person to represent them.

One thing that's important to remember is that literal numbers such as the age value in our Person example will be wrapped in NSNumber objects, so we'll need to call 'intValue' on them to get the number.

NSMutableArrary *people = [NSMutableArray array];

for (NSDictionary *dict in jsonObjects)
{
    Person *newPerson = [[[Person alloc] init] autorelease];
    [newPerson setFirstName:[dict objectForKey:@"firstName"]];
    [newPerson setLastName:[dict objectForKey:@"lastName"]];
    [newPerson setAge:[[dict objectForKey:@"age"] intValue]];
    [newPerson setAddress:[dict objectForKey:@"address"]];
    [newPerson setPhoneNumbers:[dict objectForKey:@"phoneNumber"]];

    [people addObject:newPerson];
}

And there we have it.

One final thing to take note of. You'll notice that I used literal strings as key names while creating the Person objects. It might be better for you to determine each key name that you'll be using and create a string constant for them. That way, when you're parsing your data, if you misspell firstName, the compiler can throw an error (because it won't match the name of the constant you created) and save you a lot of time debugging when, for some damn reason, you're not getting any value for @"firtName"!

An easy one to kick things off.

Need to search for places of interest, restaurants, hotels and display them on a map? Google's Local Search can help you out.

Among Google's AJAX APIs is a RESTful webservice which returns JSON formatted data for use in Flash or other non-javascript environments.

Using this webservice you can fire off a request to Google and get the same results as you would if you searched on Google Maps itself - only in a data format that is useful to you.

The base URL you'll need is:

http://ajax.googleapis.com/ajax/services/search/local?

You'll probably want to add a few parameters onto it too:

  • v=1.0 - Specify which version of the API you're attempting to call.
  • rsz=8 - Specify how many results you wish to get back (minimum 4, maximum 8 ).
  • sll=33.830296,-116.545292 - A comma separated coordinate reference that will form the center point that you're searching from.
  • q=restaurants - Your search query. This can be anything you like - perhaps you can take a string value from a search bar?.

You final URL should look something similar to:

http://ajax.googleapis.com/ajax/services/search/local?v=1.0&rsz=8&sll=33.830296,-116.545292&q=restaurants

Here's an example of how I make the request. It's pretty straightforward. I use an MKMapView in my app and use it's centerCoordinate property as the centre of my search. I take the query term from a search bar, remembering to URL encode it properly (spaces become %20, etc).

NSString *locationString = [NSString stringWithFormat:@"%.6f,%.6f", [mapView centerCoordinate].latitude, [mapView centerCoordinate].longitude];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://ajax.googleapis.com/ajax/services/search/local?v=1.0&rsz=8&sll=%@&q=%@", locationString, [[searchBar text] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];

This will give you a response with data formatted in JSON, which you can parse to access the returned locations. You can use a JSON parser such as my personal choice SBJSON or TouchJSON. A blog post on JSON parsing may come in the future.

The JSON data will contain everything you need to represent a location on the map such as it's coordinate, name, address, phone numbers, directions. Plenty of information.