Umair
Umair

Reputation: 398

Mapping json object on coredata entity using RestKIt

I am using RestKit for developing some todo list app. I am facing some mapping problem regarding returned json form server with CoreData in iOS.

The Scenario

Following is the image of list and tasks entities which i am using.

enter image description here

When someone adds a new task to the list on the server i return following Json of that particular list:

`GET www.mydomain.com\api\list\1`

        [ { "list" : 

          { "listID" : "1",
            "listName" : "New List ",
            "listSyncStatus" : "1"
          },
        "tasks" : [ { "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "24",
              "taskName" : "Server Added 2",
              "taskSyncStatus" : "1"
            },
            { "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "25",
              "taskName" : "Server Added 3",
              "taskSyncStatus" : "1"
            },
            { "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "23",
              "taskName" : "Server Added",
              "taskSyncStatus" : "1"
            }
          ]
      } 
    ]

my response descriptor for above json is as follows:

    RKResponseDescriptor *taskResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:taskEntityMapping
                                                                                            method:RKRequestMethodGET
                                                                                       pathPattern:@"/api/list/:id"
                                                                                           keyPath:@"tasks"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

and for my core data mapping i use following relationship mapping:

    [taskEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"list"
                                                                                  toKeyPath:@"list"
                                                                                withMapping:listEntityMapping]];

my taskEntityMapping is as follows:

    NSDictionary *taskObjectMapping = @{
                                    @"listID" : @"listID",
                                    @"taskID" : @"taskID",
                                    @"taskName" : @"taskName",
                                    @"taskCompletionStatus" : @"taskCompletionStatus",
                                    @"taskSyncStatus" : @"taskSyncStatus"
                                };

RKEntityMapping *taskEntityMapping = [RKEntityMapping mappingForEntityForName:@"Task" inManagedObjectStore:managedObjectStore];
[taskEntityMapping addAttributeMappingsFromDictionary:taskObjectMapping];
taskEntityMapping.identificationAttributes = @[ @"taskID" ];

and my listEntityMapping is as follows:

    //ALL LISTS RELATED REQUESTS
NSDictionary *listObjectMapping = @{
                                      @"listID" : @"listID",
                                      @"listName" : @"listName",
                                      @"listSyncStatus" : @"listSyncStatus",

                                  };

RKEntityMapping *listEntityMapping = [RKEntityMapping mappingForEntityForName:@"List" inManagedObjectStore:managedObjectStore];
[listEntityMapping addAttributeMappingsFromDictionary:listObjectMapping];

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

On execution my app crashes with following error Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected a dictionary representation'

and request log is as follows:

2014-02-03 13:17:29.789 RKGist[984:70b] T restkit.network:RKObjectRequestOperation.m:178 GET 'http://mydomain.com/api/list/1':
request.headers={
    Accept = "application/json";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    "User-Agent" = "RKGist/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)";
}
request.body=(null)
2014-02-03 13:17:30.670 RKGist[984:f03] T restkit.network:RKResponseMapperOperation.m:451 Mapping HTTP response to nil target object...
2014-02-03 13:17:30.670 RKGist[984:f03] D restkit.object_mapping:RKMapperOperation.m:377 Executing mapping operation for representation: (
        {
        list =         {
            listID = 1;
            listName = "New List ";
            listSyncStatus = 1;
        };
        tasks =         (
                        {
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 24;
                taskName = "Server Added 2";
                taskSyncStatus = 1;
            },
                        {
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 25;
                taskName = "Server Added 3";
                taskSyncStatus = 1;
            },
                        {
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 23;
                taskName = "Server Added";
                taskSyncStatus = 1;
            }
        );
    }
)
 and targetObject: (null)
2014-02-03 13:17:30.671 RKGist[984:f03] T restkit.object_mapping:RKMapperOperation.m:320 Examining keyPath 'tasks' for mappable content...
2014-02-03 13:17:30.671 RKGist[984:f03] D restkit.object_mapping:RKMapperOperation.m:297 Found mappable collection at keyPath 'tasks': (
        (
                {
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 24;
            taskName = "Server Added 2";
            taskSyncStatus = 1;
        },
                {
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 25;
            taskName = "Server Added 3";
            taskSyncStatus = 1;
        },
                {
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 23;
            taskName = "Server Added";
            taskSyncStatus = 1;
        }
    )
)

the log says found mappable collection at keypath tasks.

Can anyone guide me what am i doing wrong here. Is my returned json format wrong or my mapping code is wrong ?

Upvotes: 1

Views: 1423

Answers (1)

Wain
Wain

Reputation: 119021

You response descriptor uses keyPath:@"tasks". This effectively 'digs' into the response and ignores anything outside the tasks section. That means that during mapping you have no access to the list section.

Using addPropertyMapping: with a relationship is for nested mappings - that isn't what you have. You actually have 2 separate sections that need to be mapped individually (so, 2 response descriptors) to create all of the objects with their associated ids (and the ids of the connected objects). Then, you need to use foreign key mapping to make the connections (using RKConnectionDescription).

1 thing to check is what the JSON returned is. It appears as though it may be 1 large array containing an object and that doesn't make sense. If it is an array then you would need to change your entire approach. It should be 1 object with a number of keys...

Upvotes: 1

Related Questions