Search code examples
iosobjective-ciphonerestkitjsog

RestKit mapping for JSOG API object


I'm trying to figure out how to realize a mapping of an API response into CoreData objects using RestKit. The API uses JSOG standard. Here is an example:

[
    {
        "@id": "1",
        "name": "Sally",
        "friend": {
            "@id": "2",
            "name": "Bob",
            "friend": {
                "@id": "3",
                "name": "Fred",
                "friend": { "@ref": "1" }
            }
        }
    },
    { "@ref": "2" },
    { "@ref": "3" }
]

How would I create an RKEntityMapping for such a JSON? Mapping of simple attributes is trivial, the question is how to setup the relationships here so they work with @ref, also, when the top level user object contains the @ref only.

RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:@"Question"
                                                   inManagedObjectStore:[RKObjectManager sharedManager].managedObjectStore];

[userMapping addAttributeMappingsFromDictionary:@
 {
     @"@id" : @"identifier",
     @"name" : @"name"
 }];

[userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"friend"
                                                                            toKeyPath:@"friend"
                                                                          withMapping:userMapping]];

My guess is that i could use code below to handle the @ref inside of an object:

[userMapping addConnectionForRelationship:@"friend" connectedBy:@{@"@ref": @"@id"}];

but is it correct?

  1. How would I map either a full object or just a reference to an already-provided object (via @ref) to actual Core Data objects?
  2. How can I map the top elements of the JSON (being a list of User objects) to an actual list of User entities?

Solution

  • Add a relationship using the mapping itself, so it drills recursively. Use foreign key mapping for the refs.


    Looking at this again following your comment it may actually be a good candidate for a dynamic mapping instead of foreign key. This would mean creating a new mapping which just uses @"@ref" : @"identifier" for the connections and a dynamic mapping which looks at the keys and decides wether to use this connection mapping or the full userMapping.

    Note that both of these mappings need to specify that identifier is the unique key of the object and you should use a memory cache to allow the existing objects to be found instead of creating duplicates.