unnamedhorse
unnamedhorse

Reputation: 1823

Restkit object mapping gives null objects

I have an entity (on Core Data) called Contact, each contact has a Neighborhood, User and ContactOrigin entities related with it. When I retrive the JSON data from the server, I get something like this:

{
  "contact" : [
    {
      "prospect" : {
        "pkProspect" : 21,
        "name" : "Test Contact",
        "email" : "[email protected]",
        "phone" : "5555555555",
        "address" : "Test Avenue",
        "media" : {
          "pkMedia" : 3,
          "name" : "Referência Entrevista You Move"
        },
        "neighborhood" : {
          "pkNeighborhood" : 15857,
          "name" : "Donwtown"
        }
      },
      "user" : {
        "firstName" : "John",
        "pkPerson" : 5,
        "lastName" : "Doe"
      }
    }
  ]
}

So as you can see, I have an array of contacts and each contact has a user node, a neighborhood node and a media node (which I use as origin on my database). RestKit seems to be mapping this the right way with this code:

// Getting the object manager.
RKObjectManager *objectManager = [RKObjectManager sharedManager];

// Relationship mappings.    
RKManagedObjectMapping *neighborhoodMapping = [RKManagedObjectMapping mappingForClass:[Neighborhood class] inManagedObjectStore:objectManager.objectStore];
neighborhoodMapping.primaryKeyAttribute = @"identifier";
[neighborhoodMapping mapKeyPath:@"pkNeighborhood" toAttribute:@"identifier"];

RKManagedObjectMapping *originMapping = [RKManagedObjectMapping mappingForClass:[ContactOrigin class] inManagedObjectStore:objectManager.objectStore];
originMapping.primaryKeyAttribute = @"identifier";
[originMapping mapKeyPath:@"pkMedia" toAttribute:@"identifier"];

RKManagedObjectMapping *userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
userMapping.primaryKeyAttribute = @"identifier";
[userMapping mapKeyPath:@"pkPerson" toAttribute:@"identifier"];

// Creating the contact mapping for the request.
RKManagedObjectMapping *contactMapping = [RKManagedObjectMapping mappingForClass:[Contact class] inManagedObjectStore:objectManager.objectStore];
contactMapping.primaryKeyAttribute = kContactFieldNameId;

[contactMapping mapKeyPath:@"prospect.neighborhood" toRelationship:@"addressNeighborhood" withMapping:neighborhoodMapping];
[contactMapping mapKeyPath:@"prospect.media" toRelationship:@"origin" withMapping:originMapping];
[contactMapping mapKeyPath:@"user" toRelationship:@"user" withMapping:userMapping];

[contactMapping connectRelationship:@"addressNeighborhood" withObjectForPrimaryKeyAttribute:@"identifier"];
[contactMapping connectRelationship:@"origin" withObjectForPrimaryKeyAttribute:@"identifier"];
[contactMapping connectRelationship:@"user" withObjectForPrimaryKeyAttribute:@"identifier"];

[contactMapping mapKeyPath:@"prospect.pkProspect" toAttribute:@"identifier"];
[contactMapping mapKeyPath:@"prospect.name" toAttribute:@"name"];
[contactMapping mapKeyPath:@"prospect.email" toAttribute:@"email"];
[contactMapping mapKeyPath:@"prospect.phone" toAttribute:@"phone"];
[contactMapping mapKeyPath:@"prospect.address" toAttribute:@"address"];

// Setting the result mapping.
[objectManager.mappingProvider setObjectMapping:contactMapping forKeyPath:@"contact"];
// Loading data.
[objectManager loadObjectsAtResourcePath:resourcePath usingBlock:^(RKObjectLoader *loader) {
    loader.delegate = self;
    loader.userData = delegate;
}];

When the mapping is complete, I receive the following message (I'm showing just the User error):

2012-07-06 18:20:23.016 Contact Manager[8254:10c03] E restkit.core_data:RKManagedObjectStore.m:250 Core Data Save Error
                               NSLocalizedDescription:      The operation couldn’t be completed. (Cocoa error 1570.)
                               NSValidationErrorKey:            user
                               NSValidationErrorPredicate:  (null)
                               NSValidationErrorObject:
<Contact: 0x917dff0> (entity: Contact; id: 0x917e070 <x-coredata:///Contact/t9D9EE4AE-142A-45EC-88C1-E97833729D0C2> ; data: {
    address = "Test Avenue";
    addressNeighborhood = "0x918b5b0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/Neighborhood/p21>";
    email = "[email protected]";
    identifier = 21;
    name = "Test Contact";
    origin = nil;
    phone = 5555555555;
    user = nil;
})
2012-07-06 18:20:23.024 Contact Manager[8254:10c03] E restkit.core_data:RKManagedObjectLoader.m:167 Failed to save managed object context after mapping completed: The operation couldn’t be completed. (Cocoa error 1560.)

As you can see, both origin and user are null and this is causing a error when I try to save it on Core Data because those fields are required, but if we take a look at the logs from RestKit we'll see that those objects have been parsed correctly and in fact they exists in the database.

2012-07-06 18:20:22.938 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:636 Starting mapping operation...
2012-07-06 18:20:22.940 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:637 Performing mapping operation: RKObjectMappingOperation for 'User' object. Mapping values from object {
    firstName = John;
    lastName = Doe;
    pkPerson = 5;
} to object <User: 0x5ca9d60> (entity: User; id: 0xc5aa7a0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/User/p1> ; data: {
    contacts = "<relationship fault: 0xc5ab580 'contacts'>";
    email = "[email protected]";
    identifier = 5;
    ip = "0.0.0.0";
    isLoggedIn = 1;
    language = "en";
    name = "John Doe";
    password = 4badaee57fed5610012a296273158f5f;
}) with object mapping <RKManagedObjectMapping:0x5ca78b0 objectClass=User keyPath mappings => (
    "RKObjectKeyPathMapping: pkPerson => identifier"
)>
2012-07-06 18:20:22.942 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:330 Mapping attribute value keyPath 'pkPerson' to 'identifier'
2012-07-06 18:20:22.943 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectPropertyInspector.m:107 Cached property names and types for Class 'User': {
    accessibilityHint = NSString;
    accessibilityLabel = NSString;
    accessibilityLanguage = NSString;
    accessibilityValue = NSString;
    contacts = NSSet;
    email = NSString;
    identifier = NSNumber;
    ip = NSString;
    isLoggedIn = NSNumber;
    language = NSString;
    name = NSString;
    password = NSString;
}
2012-07-06 18:20:22.944 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:347 Skipped mapping of attribute value from keyPath 'pkPerson to keyPath 'identifier' -- value is unchanged (5)
2012-07-06 18:20:22.946 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:643 Finished mapping operation successfully...
2012-07-06 18:20:22.966 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:597 Mapped relationship object from keyPath 'user' to 'user'. Value: <User: 0x5ca9d60> (entity: User; id: 0xc5aa7a0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/User/p1> ; data: {
    contacts = "<relationship fault: 0xc5ab580 'contacts'>";
    email = "[email protected]";
    identifier = 5;
    ip = "0.0.0.0";
    isLoggedIn = 1;
    language = "pt_BR";
    name = "John Doe";
    password = 4badaee57fed5610012a296273158f5f;
})
2012-07-06 18:20:22.968 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:643 Finished mapping operation successfully...

So, my question here is why user and origin are null if the parser found those objects into the database? Is there anything wrong with the mapping?

Upvotes: 2

Views: 1874

Answers (1)

unnamedhorse
unnamedhorse

Reputation: 1823

After a lot of debugging I found a way to fix it. First, the fact that I was using the same primary key (@"identifier") for every object, was messing up with the mapping.

After that, I've removed the [contactMapping connectRelationship:withObjectForPrimaryKeyAttribute:] because it's not needed and now everything seems to be working.

Upvotes: 2

Related Questions