Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON and Core Data on the iPhone

I have a core data object graph (consisting of two entities linked by a to-many relationship).

I was curious, as a relatively inexperienced iPhone developer, whether anyone could recommend an approach, and a suitable JSON implementation for the iPhone, which would allow me to:

  1. convert the core data records into a JSON string (whilst maintaining the relationship between the entities); and

  2. convert the JSON string back into core data objects (again preserving the relationship between entities).

I have searched, unsuccessfully, for a tutorial/code sample on this point so any assistance would be gratefully received.

like image 898
Urizen Avatar asked Mar 02 '10 10:03

Urizen


People also ask

What is core data on iPhone?

Core Data is a framework that you use to manage the model layer objects in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence.

Does iOS use JSON?

Based on a subset of the JavaScript programming language, JSON is a first-class citizen when dealing with JavaScript applications. Thanks to JSON's simplicity, almost all programming languages provide inherent support for it—including the Swift programming language used in iOS development.

What is iOS JSON?

JSON (JavaScript Object Notation) is a lightweight format, which is widely used to send data over the internet. The JSON format includes dictionaries and arrays. In this tutorial some data is requested from a web server and displayed on screen. This tutorial is made with Xcode 10 and built for iOS 12.

What is JSON data used for?

It is a text-based way of representing JavaScript object literals, arrays, and scalar data. JSON is relatively easy to read and write, while also easy for software to parse and generate. It is often used for serializing structured data and exchanging it over a network, typically between a server and web applications.


2 Answers

I just wanted to point out a small typo, that caused the code to crash, and hopefully this will save you a few min.

- (NSArray*)dataStructuresFromManagedObjects:(NSArray*)managedObjects {      NSMutableArray *dataArray = [[NSArray alloc] init];     for (NSManagedObject *managedObject in managedObjects) {         [dataArray addObject:[self dataStructureFromManagedObject:managedObject]];     }     return [dataArray autorelease]; } 

The NSMutableArray *dataArray = [[NSArray alloc] init]; // This should be NSMutableArray

really should be NSMutableArray *dataArray = [[NSMutableArray alloc] init];

that is all.

thank you

like image 34
creativeKoder Avatar answered Oct 05 '22 20:10

creativeKoder


First, pick a JSON library to use, I personally like TouchJSON but several others out there are quite nice as well. The complicated part, although not very hard, is to convert your managed objects into suitable structures for the conversion. I wrote this real quick so it may have an error or two :)

The methods you call are:

- (NSString*)jsonStructureFromManagedObjects:(NSArray*)managedObjects; - (NSArray*)managedObjectsFromJSONStructure:(NSString*)json withManagedObjectContext:(NSManagedObjectContext*)moc; 

And the implementation is as follows:

- (NSDictionary*)dataStructureFromManagedObject:(NSManagedObject*)managedObject {   NSDictionary *attributesByName = [[managedObject entity] attributesByName];   NSDictionary *relationshipsByName = [[managedObject entity] relationshipsByName];   NSMutableDictionary *valuesDictionary = [[managedObject dictionaryWithValuesForKeys:[attributesByName allKeys]] mutableCopy];   [valuesDictionary setObject:[[managedObject entity] name] forKey:@"ManagedObjectName"];   for (NSString *relationshipName in [relationshipsByName allKeys]) {     NSRelationshipDescription *description = [[[managedObject entity] relationshipsByName] objectForKey:relationshipName];     if (![description isToMany]) {       NSManagedObject *relationshipObject = [managedObject valueForKey:relationshipName];       [valuesDictionary setObject:[self dataStructureForManagedObject:relationshipObject] forKey:relationshipName];       continue;     }     NSSet *relationshipObjects = [managedObject objectForKey:relationshipName];     NSMutableArray *relationshipArray = [[NSMutableArray alloc] init];     for (NSManagedObject *relationshipObject in relationshipObjects) {       [relationshipArray addObject:[self dataStructureForManagedObject:relationshipObject]];     }     [valuesDictionary setObject:relationshipArray forKey:relationshipName];   }   return [valuesDictionary autorelease]; }  - (NSArray*)dataStructuresFromManagedObjects:(NSArray*)managedObjects {   NSMutableArray *dataArray = [[NSMutableArray alloc] init];   for (NSManagedObject *managedObject in managedObjects) {     [dataArray addObject:[self dataStructureForManagedObject:managedObject]];   }   return [dataArray autorelease]; }  - (NSString*)jsonStructureFromManagedObjects:(NSArray*)managedObjects {   NSArray *objectsArray = [self dataStructuresFromManagedObjects:managedObjects];   NSString *jsonString = [[CJSONSerializer serializer] serializeArray:objectsArray];   return jsonString; }  - (NSManagedObject*)managedObjectFromStructure:(NSDictionary*)structureDictionary withManagedObjectContext:(NSManagedObjectContext*)moc {   NSString *objectName = [structureDictionary objectForKey:@"ManagedObjectName"];   NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:objectName inManagedObjectContext:moc];   [managedObject setValuesForKeysWithDictionary:structureDictionary];    for (NSString *relationshipName in [[[managedObject entity] relationshipsByName] allKeys]) {     NSRelationshipDescription *description = [relationshipsByName objectForKey:relationshipName];     if (![description isToMany]) {       NSDictionary *childStructureDictionary = [structureDictionary objectForKey:relationshipName];       NSManagedObject *childObject = [self managedObjectFromStructure:childStructureDictionary withManagedObjectContext:moc];       [managedObject setObject:childObject forKey:relationshipName];       continue;     }     NSMutableSet *relationshipSet = [managedObject mutableSetForKey:relationshipName];     NSArray *relationshipArray = [structureDictionary objectForKey:relationshipName];     for (NSDictionary *childStructureDictionary in relationshipArray) {       NSManagedObject *childObject = [self managedObjectFromStructure:childStructureDictionary withManagedObjectContext:moc];       [relationshipSet addObject:childObject];     }   }   return managedObject; }  - (NSArray*)managedObjectsFromJSONStructure:(NSString*)json withManagedObjectContext:(NSManagedObjectContext*)moc {   NSError *error = nil;   NSArray *structureArray = [[CJSONDeserializer deserializer] deserializeAsArray:json error:&error];   NSAssert2(error == nil, @"Failed to deserialize\n%@\n%@", [error localizedDescription], json);   NSMutableArray *objectArray = [[NSMutableArray alloc] init];   for (NSDictionary *structureDictionary in structureArray) {     [objectArray addObject:[self managedObjectFromStructure:structureDictionary withManagedObjectContext:moc]];   }   return [objectArray autorelease]; } 

Now this is recursive so you can easily end up translating your entire persistent store if you are not careful. Watch your relationships and make sure that they only go "down" the object tree so that you only get the objects you want translated.

like image 74
Marcus S. Zarra Avatar answered Oct 05 '22 19:10

Marcus S. Zarra