0
votes

I have recently had recourse to get my postcode data from Google Maps API. At the end of this question I have included a large snippet of the JSON response string that I receive from Google.

Deep in my code I get the response and I parse it using the TouchJSON library from Jonathan Wight. This is my code

NSStringEncoding encoding;

// Fetch data from web service.
NSString *jsonString = [NSString stringWithContentsOfURL:url usedEncoding:&encoding error:nil];
// Process JSON data returned from web service.
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];

if (jsonString == nil)
{
// bah
} else if (![self isCancelled]) {// Check to see if we have been cancelled.

    if (dictionary) {
        NSArray* results = [dictionary objectForKey:@"results"];
        NSDictionary* types = [results objectAtIndex:1];
        NSArray* address_components = [types objectForKey:@"address_components"];
        NSDictionary* postcodes = [address_components objectAtIndex:0];
        NSString* postcode = [postcodes objectForKey:@"long_name"];
    // do stuff with the postcode
    }
//
}

Notice how I get the types dictionary and the postcodes dictionary by using a specific offset in an NSArray. My question is really this,

How can I parse the JSON string (preferably using TouchJSON) without having to hard code those array offsets?

It strikes me that the Google Maps response string may be subject to change and my hard coded approach would stop working at that point. Has anyone out there used a similar but more robust approach that they would be willing too share here?

...Google Maps API sample response string... The 'target' postcode is highlighted in bold

{ "status": "OK", "results": [ { "types": [ "street_address" ], "formatted_address": "9 Clarendon Pl, Leamington Spa, Warwickshire CV32 5, UK", "address_components": [ { "long_name": "9", "short_name": "9", "types": [ "street_number" ] }, { "long_name": "Clarendon Pl", "short_name": "A452", "types": [ "route" ] }, { "long_name": "Leamington Spa", "short_name": "Leamington Spa", "types": [ "locality", "political" ] }, { "long_name": "Warwick", "short_name": "Warwick", "types": [ "administrative_area_level_3", "political" ] }, { "long_name": "Warwickshire", "short_name": "Warks", "types": [ "administrative_area_level_2", "political" ] }, { "long_name": "England", "short_name": "England", "types": [ "administrative_area_level_1", "political" ] }, { "long_name": "United Kingdom", "short_name": "GB", "types": [ "country", "political" ] }, { "long_name": "CV32 5", "short_name": "CV32 5", "types": [ "postal_code_prefix", "postal_code" ] } ], "geometry": { "location": { "lat": 52.2919849, "lng": -1.5399505 }, "location_type": "RANGE_INTERPOLATED", "viewport": { "southwest": { "lat": 52.2888374, "lng": -1.5431216 }, "northeast": { "lat": 52.2951326, "lng": -1.5368264 } }, "bounds": { "southwest": { "lat": 52.2918320, "lng": -1.5399760 }, "northeast": { "lat": 52.2921380, "lng": -1.5399720 } } } }, { "types": [ "postal_code" ], "formatted_address": "Leamington Spa, Warwickshire CV32 5LD, UK", "address_components": [ { "long_name": "CV32 5LD", "short_name": "CV32 5LD", "types": [ "postal_code" ] }, { "long_name": "Leamington Spa", "short_name": "Leamington Spa", "types": [ "locality", "political" ] }, ......... lots more JSON follows

1

1 Answers

2
votes

I've never used TouchJSON, but it appears to me that your hardcoded offsets are there because you expect only one result, but Google Maps API is flexible enough to return multiple results. In fact, where you have objectAtIndex:1 suggests that you are taking the second result set, so the code you've written is actually dependent on there being at least two results.

Even if I've gotten the details wrong there, I suspect what you really want to do instead of NSDictionary* types = [results objectAtIndex:1]; is something more like:

NSDictionary* types = [results objectAtIndex:[results indexOfObjectPassingTest:yourPredicateHere]];

If you don't know how predicates work, you'll want to read Apple's Predicate Programming Guide first to figure out how to set your predicate (the thing that I labeled yourPredicateHere above). http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/predicates.html