iOS Programming: Preparing CoreData for JSON transmission

Posted By Will Larche In Mobile 02/20/2012

Sometimes you spend way too much time googling a question when you have the power to answer it yourself. Man has become increasingly forgetful as it learns to retrieve information from the web. You can read about it here but chances are you won't retain much. (Don't believe me? How are your times tables?  Name the planets.  Go someplace new without your GPS...Yeah I thought so!)

Coding is a career that VERY much suffers from this phenomenon. If something is unknown, we search search search for documentation of someone doing it first. BUT sometimes we have all the tools we need to do something already.

I have some NSManagedObjects. They contain data. I need to send that with JSON over the web. 

It seems so simple that I thought 'There must be a method either in the Apple docs or in my SBJSON framework'.  Of course nothing came up on Google so then I thought 'I'm so stupid; There's probably a 3rd party framework JUST FOR THIS!' But, um, duh, no there is not. Because it's so simple and I already knew how to do it.


To get started, make yourself some categories.

1. File -> New -> New File

2. iOS -> CocoaTouch -> Objective-C Category

3. Category: name it something useful like "JSON_Dicts"

4. Category on: The class we're dealing with (the NSManagedObject the CoreData code generator made us). 
Observe: You now have a category on your class that should be named thusly: "[class name]+JSON_Dicts".

5. Declare the following in the new category's .h file: 

- (NSDictionary *)jsonDictionary;


6. Implement that sucker. For this example I'll use an NSManagedObject from a project I'm working on involving adding "Animal" entries into a database:

- (NSDictionary *)jsonDictionary
{
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:10];
if (self.age) {
[dictionary setObject:self.age forKey:@"age"];
} else {
[dictionary setObject:nil forKey:@"age"];
}

if (self.gender) {
[dictionary setObject:self.gender forKey:@"gender"];
} else {
[dictionary setObject:nil forKey:@"gender"];
}

if (self.namestring) {
[dictionary setObject:self.namestring forKey:@"namestring"];
} else {
[dictionary setObject:nil forKey:@"namestring"];
}

if (self.numberofanimals) {
[dictionary setObject:self.numberofanimals forKey:@"numberofanimals"];
} else {
[dictionary setObject:nil forKey:@"numberofanimals"];
}

if (self.size) {
[dictionary setObject:self.size forKey:@"sizeint"];
} else {
[dictionary setObject:nil forKey:@"sizeint"];
}

if (self.species) {
[dictionary setObject:self.species forKey:@"species"];
} else {
[dictionary setObject:nil forKey:@"species"];
}

if (self.status) {
[dictionary setObject:self.status forKey:@"status"];
} else {
[dictionary setObject:nil forKey:@"status"];
}

return dictionary;
}

Das it!

7. Send that to your JSON encoder. I use SBJSON so my message looks like this:

NSString *jsonString = [animal.jsonDictionary JSONRepresenation];

It'll come out looking like this (for example):

jsonRepresentation: {"age":2,"namestring":"RMA","gender":1,"numberofanimals":1,
"sizeint":2,"status":0,"species":"Cat"}

Anybody have any suggested improvements?

Comments

I hope this comes out as code :)

I have a global.managedObjectContext, and this method takes an Entity Name and just cycles through each attribute, creating a NSDictionary for each value (but not doing anything with it)

-(void)backupDataForEntityName:(NSString *)entityName
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:global.managedObjectContext];
[request setEntity:entity];

NSArray *array = [[global.managedObjectContext executeFetchRequest:request error:nil] mutableCopy];

for (NSManagedObject *managedObject in array) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];

for (NSPropertyDescription *property in entity) {
if ([property isKindOfClass:[NSAttributeDescription class]]) {
if ([managedObject valueForKey:property.name]) {
[dictionary setObject:[managedObject valueForKey:property.name] forKey:property.name];
}
else {
[dictionary setObject:nil forKey:property.name];
}
}
}
NSLog(@"Dictionary: %@", dictionary);
}
}

Leave a Comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
To prevent automated spam submissions leave this field empty.
By submitting this form, you accept the Mollom privacy policy.