From ca7ccfee89d570b2e91d895cc4e12fba160dc2fc Mon Sep 17 00:00:00 2001 From: Carl Brown Date: Thu, 23 Aug 2012 08:01:44 -0500 Subject: [PATCH] Better type checking during JSON parsing --- SeismicJSON/EarthquakeFetchOperation.m | 95 ++++++++++++++------------ 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/SeismicJSON/EarthquakeFetchOperation.m b/SeismicJSON/EarthquakeFetchOperation.m index 933eae8..a1c2ace 100644 --- a/SeismicJSON/EarthquakeFetchOperation.m +++ b/SeismicJSON/EarthquakeFetchOperation.m @@ -36,53 +36,60 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection { id objectFromJSON = [NSJSONSerialization JSONObjectWithData:self.fetchedData options:0 error:&error]; if (objectFromJSON) { #if kUSE_NSNOTIFICATIONS_FOR_CONTEXT_MERGE - NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; - [context setPersistentStoreCoordinator:self.mainContext.persistentStoreCoordinator]; + NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; + [context setPersistentStoreCoordinator:self.mainContext.persistentStoreCoordinator]; #else NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; - [context setParentContext:[self mainContext]]; + [context setParentContext:[self mainContext]]; #endif - NSDictionary *jsonDict = (NSDictionary *) objectFromJSON; - if (jsonDict) { + if ([objectFromJSON isKindOfClass:[NSDictionary class]]) { - NSArray *events = [jsonDict objectForKey:@"features"]; + NSDictionary *jsonDict = (NSDictionary *) objectFromJSON; - if (events) { + + if ([[jsonDict objectForKey:@"features"] isKindOfClass:[NSArray class]]) { - for (NSDictionary *eventDict in events) { - - NSString *eventLocation = [eventDict valueForKeyPath:@"properties.place"]; - NSDate *eventDate = [NSDate dateWithTimeIntervalSince1970:[[eventDict valueForKeyPath:@"properties.time"] doubleValue]]; - NSNumber *eventLong = [NSNumber numberWithDouble:[[[eventDict valueForKeyPath:@"geometry.coordinates"] objectAtIndex:0] doubleValue]]; - NSNumber *eventLat =[NSNumber numberWithDouble:[[[eventDict valueForKeyPath:@"geometry.coordinates"] objectAtIndex:1] doubleValue]]; - NSNumber *eventMagnitude = [NSNumber numberWithFloat:[[eventDict valueForKeyPath:@"properties.mag"] floatValue]]; - NSString *eventWebPath = [@"http://earthquake.usgs.gov" stringByAppendingPathComponent:[eventDict valueForKeyPath:@"properties.url"]]; + NSArray *events = [jsonDict objectForKey:@"features"]; + + for (NSObject *arrayElement in events) { - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Earthquake class])]; - [fetchRequest setFetchLimit:1]; - NSPredicate *eventInfo = [NSPredicate predicateWithFormat:@"location = %@ AND date = %@", - eventLocation, - eventDate]; - [fetchRequest setPredicate:eventInfo]; - NSError *fetchError=nil; - NSArray *existingEventsMatchingThisOne = [context executeFetchRequest:fetchRequest error:&fetchError]; - if (existingEventsMatchingThisOne==nil) { - NSLog(@"Error checking for existing record: %@",[fetchError localizedDescription]); - } else if ([existingEventsMatchingThisOne count]==0) { + if ([arrayElement isKindOfClass:[NSDictionary class]]) { + NSDictionary *eventDict = (NSDictionary *) arrayElement; - //Didn't find one already, make a new one - NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Earthquake class]) inManagedObjectContext:context]; - [newManagedObject setValue:eventLocation forKey:@"location"]; - [newManagedObject setValue:eventDate forKey:@"date"]; - [newManagedObject setValue:eventLat forKey:@"latitude"]; - [newManagedObject setValue:eventLong forKey:@"longitude"]; - [newManagedObject setValue:eventMagnitude forKey:@"magnitude"]; - [newManagedObject setValue:eventWebPath forKey:@"webLinkToUSGS"]; + NSString *eventLocation = [eventDict valueForKeyPath:@"properties.place"]; + NSDate *eventDate = [NSDate dateWithTimeIntervalSince1970:[[eventDict valueForKeyPath:@"properties.time"] doubleValue]]; + NSNumber *eventLong = [NSNumber numberWithDouble:[[[eventDict valueForKeyPath:@"geometry.coordinates"] objectAtIndex:0] doubleValue]]; + NSNumber *eventLat =[NSNumber numberWithDouble:[[[eventDict valueForKeyPath:@"geometry.coordinates"] objectAtIndex:1] doubleValue]]; + NSNumber *eventMagnitude = [NSNumber numberWithFloat:[[eventDict valueForKeyPath:@"properties.mag"] floatValue]]; + NSString *eventWebPath = [@"http://earthquake.usgs.gov" stringByAppendingPathComponent:[eventDict valueForKeyPath:@"properties.url"]]; + + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Earthquake class])]; + [fetchRequest setFetchLimit:1]; + NSPredicate *eventInfo = [NSPredicate predicateWithFormat:@"location = %@ AND date = %@", + eventLocation, + eventDate]; + [fetchRequest setPredicate:eventInfo]; + NSError *fetchError=nil; + NSArray *existingEventsMatchingThisOne = [context executeFetchRequest:fetchRequest error:&fetchError]; + if (existingEventsMatchingThisOne==nil) { + NSLog(@"Error checking for existing record: %@",[fetchError localizedDescription]); + } else if ([existingEventsMatchingThisOne count]==0) { + + //Didn't find one already, make a new one + NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Earthquake class]) inManagedObjectContext:context]; + + [newManagedObject setValue:eventLocation forKey:@"location"]; + [newManagedObject setValue:eventDate forKey:@"date"]; + [newManagedObject setValue:eventLat forKey:@"latitude"]; + [newManagedObject setValue:eventLong forKey:@"longitude"]; + [newManagedObject setValue:eventMagnitude forKey:@"magnitude"]; + [newManagedObject setValue:eventWebPath forKey:@"webLinkToUSGS"]; + } + } - } // Save the context. @@ -94,15 +101,15 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection { abort(); } #if kUSE_PARENT_CONTEXTS_FOR_CONTEXT_MERGE - dispatch_sync(dispatch_get_main_queue(), ^{ - NSError *error = nil; - if (![self.mainContext save:&error]) { - // Replace this implementation with code to handle the error appropriately. - // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - NSLog(@"Unresolved error %@, %@", error, [error userInfo]); - abort(); - } - }); + dispatch_sync(dispatch_get_main_queue(), ^{ + NSError *error = nil; + if (![self.mainContext save:&error]) { + // Replace this implementation with code to handle the error appropriately. + // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + NSLog(@"Unresolved error %@, %@", error, [error userInfo]); + abort(); + } + }); #endif } }