2
votes

I have the following JSON:

{
    "users": [
        {"id": "1", "name": "John Doe"},
        {"id": "2", "name": "Bill Nye"}
    ],
    "groups": [
        {"id": "1", "name": "Group1", "users": ["1", "2"]},
        {"id": "2", "name": "Group2", "users": ["1"]}
    ]
}

...and a Core Data model with User and Group objects. The group object has a to-many relationship (NSSet) to users.

I have found the following thread that seems to indicate that this is possible, but contains no explanation of how such a mapping is to be performed:

https://github.com/RestKit/RestKit/issues/284

How do I perform this mapping such that each Group's "users" relationship is properly connected?

Note: I have mappings set up that correctly map the JSON users and groups to their respective Core Data objects. However, each group's "users" NSSet is empty.

2

2 Answers

3
votes

So, I figured this out using RestKit 0.20(pre2).

JSON needed to be changed to the following (note the attribute names in the group's users array):

{
    "users": [
        {"id": "1", "name": "John Doe"},
        {"id": "2", "name": "Bill Nye"}
    ],
    "groups": [
        {"id": "1", "name": "Group1", "users": [{"id" : "1"}, {"id" : "2"}]},
        {"id": "2", "name": "Group2", "users": [{"id" : "1"}]}
    ]
}

Then, the following mappings:

RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:@"User" inManagedObjectStore:managedObjectStore];
userMapping.identificationAttributes = @[@"id"];
[userMapping addAttributeMappingsFromArray:@[@"id", @"name"]];
RKEntityMapping *groupMapping = [RKEntityMapping mappingForEntityForName:@"Group" inManagedObjectStore:managedObjectStore];
groupMapping.identificationAttributes = @[@"id"];
[groupMapping addAttributeMappingsFromArray:@[@"id", @"name"]];
[groupMapping addRelationshipMappingWithSourceKeyPath:@"users" mapping:userMapping];

And finally, the following responseDescriptors:

RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:classMapping pathPattern:@"/api/allthejson" keyPath:@"users" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKResponseDescriptor *groupResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:classMapping pathPattern:@"/api/allthejson" keyPath:@"groups" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptorsArray:@[userResponseDescriptor, groupResponseDescriptor]];

Then get your objects using RKObjectManager's getObjectsAtPath:parameters:success:failure method and your done!

1
votes

RestKit has many issues especially when it comes to modeling relationships. Debugging the mappings can be daunting.

Here is some code that deals with what you describe without RestKit.

NSArray *userArray; 
// an array populated with NSManagedObjects 
// correctly converted from JSON to the User entity

NSArray *groups = [jsonObject objectForKey:@"groups"];

for (NSDictionary *d in groups) {
   Group *g = [NSEntityDescription insertNewObjectForEntityForName:@"Group"
                  inManagedObjectContext:_managedObjectContext];
   g.id = @([d[@"id"] intValue]);
   g.name = d[@"name"];
   NSArray *users = d[@"users"];
   for (NSString *s in users) {
      User *u = [[userArray filteredArrayUsingPredicate:
        [NSPredicate predicateWithFormat:@"id = %@", @([s intValue])]]
          objectAtIndex:0];
      [g addUsersObject:u];
   }
}
// save