Search code examples
iosiphonejsonrestkitfoursquare

Using RKDynamicMapping on Foursquare's Lists API to capture lists


I'm looking to get all of my Foursquare Lists into Core Data. I'd like to use Restkit to accomplish this. The structure of the /v2/users/self/lists response is:

 "response": {
    "lists": {
        "count": 8,
        "groups": [
            {
                "type": "created",
                "name": "Lists You've Created",
                "count": 6,
                "items": [
                    {
                        "id": "13250/todos",
                        "name": "My to-do list", ...
                        }
                    {
                      "id": "13251/something",
                        "name": "Some List", ...
                    },
                    {
                      "id": "13252/somethingelse",
                        "name": "Some Other List", ...
                    }
                ]
            },
            {
                "type": "followed",
                "name": "Lists You've Saved",
                "count": 1,
                "items": [
                    {
                        "id": "5105e3cae4b0e721ca7b400a",
                        "name": "Portland's Best Coffee - 2012", ...
                      }
                     {
                      ...
                    }
                ]
            }
        ]
    }

As you can see there are 2 lists under the keyPath response.lists.groups. Ultimately I'd like to merge those 2 lists into 1, but I'd be happy with getting 2 separate lists.

I've set up my mappings as follows:

RKEntityMapping* listMapping = [RKEntityMapping mappingForEntityForName:[FOFSList entityName]
                                                   inManagedObjectStore:objectManager.managedObjectStore];
[listMapping addAttributeMappingsFromDictionary:@{
                                                     @"id": @"listID",
                                                     @"title": @"name",
                                                     @"description": @"desc",
                                                     @"user": @"user",
                                                     @"following": @"following",
                                                     @"collaborative": @"collaborative",
                                                     @"canonicalUrl": @"canonicalUrl",
                                                     @"venueCount": @"venueCount",
                                                     @"visitedCount": @"visitedCount"
                                                     }];

RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
[listMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil
                                                                            toKeyPath:@"items"
                                                                          withMapping:dynamicMapping]];

RKResponseDescriptor *listResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listMapping
                                                                                         method:RKRequestMethodGET
                                                                                       pathPattern:nil
                                                                                           keyPath:@"response.lists.groups"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:listResponseDescriptor];
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
    if ([[representation valueForKey:@"type"] isEqualToString:@"created"]) {
        return listMapping;
    } else if ([[representation valueForKey:@"type"] isEqualToString:@"followed"]) {
        return listMapping;
    }

    return nil;
}];

listMapping.identificationAttributes = @[ @"listID" ];

I end up with an error:

* Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key propertyMappings.'

Am I supposed to be using RKDynamicMappings? Is there some trick that I'm missing for parsing a response that is styled like this?


Solution

  • For those that are interested, I got a little bit creative with the RKResponseDescriptor

     RKResponseDescriptor *listResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listMapping
                                                                                                method:RKRequestMethodGET
                                                                                           pathPattern:nil
                                                                                               keyPath:@"[email protected]"
                                                                                           statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    

    See the collection operation @distinctUinionOfArrays was ultimately what got me what I needed. It makes a union of the 2 groups arrays, then I grab the items key from each of the objects in the union of the arrays.