0

Trying map this json

{
    "result": [
        {
            "group_id": 3,
            "name": "_8",
            "parent_id": [
                1,
                4039
            ],
            "position": 6,
            "title": "/8",
            "id": 18624
        },
        {
            "group_id": 3,
            "name": "02",
            "parent_id": [
                1,
                3118
            ],
            "position": 13,
            "title": "02",
            "id": 18551
        }
],
    "metadata": {
        "resultset": {
            "count": 2373,
            "limit": 100,
            "offset": 0
        }
    }
}

I use next mapping:

 RKEntityMapping *groupMapping = [RKEntityMapping mappingForEntityForName:@"Group" inManagedObjectStore:managedObjectStore];
            groupMapping.identificationAttributes = @[ @"groupID" ];
            // If source and destination key path are the same, we can simply add a string to the array
            [groupMapping addAttributeMappingsFromArray:@[ @"name", @"title" ]];
            [groupMapping addAttributeMappingsFromDictionary:@{
             @"id": @"groupID"
            }];

            RKEntityMapping *groupValuesMapping = [RKEntityMapping mappingForEntityForName:@"GroupValue" inManagedObjectStore:managedObjectStore];
            groupValuesMapping.identificationAttributes = @[ @"valueID", @"groupID" ];
            [groupValuesMapping addAttributeMappingsFromArray:@[ @"name", @"title", @"position", @"popular" ]];
            [groupValuesMapping addAttributeMappingsFromDictionary:@{
             @"id": @"valueID",
             @"group_id": @"groupID"
            }];

            RKEntityMapping *parentsMapping = [RKEntityMapping mappingForEntityForName:@"Parent" inManagedObjectStore:managedObjectStore];
            parentsMapping.identificationAttributes = @[ @"parentID" ];
            [parentsMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"parentID"]];

            RKRelationshipMapping *parentsRelationshipMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:@"parent_id"
                                                                                                            toKeyPath:@"parents"
                                                                                                          withMapping:parentsMapping];
            parentsRelationshipMapping.assignmentPolicy = RKReplaceAssignmentPolicy;
            [groupValuesMapping addPropertyMapping:parentsRelationshipMapping];

            RKObjectMapping *metadataMapping = [RKObjectMapping mappingForClass:[Metadata class]];
            [metadataMapping addAttributeMappingsFromArray:@[ @"count", @"limit", @"offset" ]];

            RKObjectMapping *containerMapping = [RKObjectMapping mappingForClass:[GroupValueContainer class]];
            [containerMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"metadata.resultset"
                                                                                            toKeyPath:@"metadata"
                                                                                          withMapping:metadataMapping]];
            [containerMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"result"
                                                                                            toKeyPath:@"groupValues"
                                                                                          withMapping:groupValuesMapping]];

Everything is maps ok, except parent_id structure. Is anybody knows, what I forgot? parentID set is always empty...

GroupValue.h is

@class Group, Parent;

@interface GroupValue : NSManagedObject

@property (nonatomic, retain) NSNumber * groupID;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * position;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSNumber * valueID;
@property (nonatomic, retain) NSNumber * popular;
@property (nonatomic, retain) Group *group;
@property (nonatomic, retain) NSSet *parents;
@end

@interface GroupValue (CoreDataGeneratedAccessors)

- (void)addParentsObject:(Parent *)value;
- (void)removeParentsObject:(Parent *)value;
- (void)addParents:(NSSet *)values;
- (void)removeParents:(NSSet *)values;

@end

GroupValueContainer.h is

@interface GroupValueContainer : NSObject

@property (nonatomic, strong) NSArray *groupValues;
@property (nonatomic, strong) Metadata *metadata;

@end

Parent.h is

@class GroupValue;

@interface Parent : NSManagedObject

@property (nonatomic, retain) NSNumber * parentID;
@property (nonatomic, retain) GroupValue *groupValue;

@end

EDITED

Here are logs:

Performing nested object mapping using mapping <RKRelationshipMapping: 0x1f5cb240 result => groupValues> for data: {
"group_id" = 3;
id = 18624;
name = "_8";
"parent_id" =     (
    1,
    4039
);
position = 6;
title = "/8";
}
Mapping attribute value keyPath 'name' to 'name'
Skipped mapping of attribute value from keyPath 'name to keyPath 'name' -- value is unchanged (_8)
Mapping attribute value keyPath 'title' to 'title'
Skipped mapping of attribute value from keyPath 'title to keyPath 'title' -- value is unchanged (/8)
Mapping attribute value keyPath 'position' to 'position'
Skipped mapping of attribute value from keyPath 'position to keyPath 'position' -- value is unchanged (6)
Did not find mappable attribute value keyPath 'popular'
Mapping attribute value keyPath 'id' to 'valueID'
Skipped mapping of attribute value from keyPath 'id to keyPath 'valueID' -- value is unchanged (18624)
Mapping attribute value keyPath 'group_id' to 'groupID'
Skipped mapping of attribute value from keyPath 'group_id to keyPath 'groupID' -- value is unchanged (3)
Mapping one to many relationship value at keyPath 'parent_id' to 'parents'
Performing nested object mapping using mapping <RKRelationshipMapping: 0x1f5cb070 parent_id => parents> for data: 1
Starting mapping operation...
Performing mapping operation: <RKMappingOperation 0x1f50e060> for 'Parent' object. Mapping values from object 1 to object <Parent: 0x2018add0> (entity: Parent; id: 0x20159ec0 <x-coredata://DC16066E-D7ED-4AB4-BC94-36528E3818EC/Parent/p2> ; data: {
groupValue = nil;
parentID = 1;
}) with object mapping (null)
Mapping attribute value keyPath '(null)' to 'parentID'
Skipped mapping of attribute value from keyPath '(null) to keyPath 'parentID' -- value is unchanged (1)
Finished mapping operation successfully...
Performing nested object mapping using mapping <RKRelationshipMapping: 0x1f5cb070 parent_id => parents> for data: 4039
Starting mapping operation...
Performing mapping operation: <RKMappingOperation 0x1f50e060> for 'Parent' object. Mapping values from object 4039 to object <Parent: 0x1f50cac0> (entity: Parent; id: 0x2015a300 <x-coredata://DC16066E-D7ED-4AB4-BC94-36528E3818EC/Parent/p48> ; data: {
groupValue = nil;
parentID = 4039;
}) with object mapping (null)
Mapping attribute value keyPath '(null)' to 'parentID'
Skipped mapping of attribute value from keyPath '(null) to keyPath 'parentID' -- value is unchanged (4039)
Finished mapping operation successfully...
Found transformable value at keyPath 'parent_id'. Transforming from type '__NSArrayM' to 'NSSet'
Mapping a to-many relationship for an `NSManagedObject`. About to apply value via mutable[Set|Array]ValueForKey
Mapped `NSSet` relationship object from keyPath 'parent_id' to 'parents'. Value: {(
<Parent: 0x2018add0> (entity: Parent; id: 0x20159ec0 <x-coredata://DC16066E-D7ED-4AB4-BC94-36528E3818EC/Parent/p2> ; data: {
groupValue = nil;
parentID = 1;
}),
<Parent: 0x1f50cac0> (entity: Parent; id: 0x2015a300 <x-coredata://DC16066E-D7ED-4AB4-BC94-36528E3818EC/Parent/p48> ; data: {
groupValue = nil;
parentID = 4039;
})
)}
Finished mapping operation successfully...

All seems to be ok, parents are saved, but connection is broken

EDITED 2

Found what is wrong. Every GroupValue must contain multiply Parents, but when creating Parent entity RestKit unify it with parentID and replace existed with new. Is it possible to keep Parent entities for every GroupValue? Is it any method not to unify entities? Not setting identificationAttributes doesn't help

1 Answer 1

1

You can't directly map from the array of ids in the JSON to connect the relationship. The relationship connection needs to be done as a foreign key mapping. This means the contents of parent_id need to be mapped into a (temporary) attribute on your class (parentIds) and then the relationship mapping uses that attribute via an RKConnectionDescription. Something like:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"GroupValue" inManagedObjectContext:managedObjectContext];
NSRelationshipDescription *parents = [entity relationshipsByName][@"parents"]; // To many relationship
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:parents attributes:@{ @"parentIds": @"parentID" }];
Sign up to request clarification or add additional context in comments.

11 Comments

could you provide more detailed information, what I need to do with connection and where to use this code in my case?
You add the connection to your mapping. The mapping will copy the array of ids to the object and then use that array to connect the destination objects.
What is parentIds and what type I should use for parentIds in Managed model? I'm trying this: [groupValuesMapping addConnectionForRelationship:@"parents" connectedBy:@{ @"parents": @"parentID" }]; and get exception *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot connect relationship: invalid attributes given for source entity 'GroupValue': parents'
parentIds is a new attribute that you add to the entity. It should be a transformable type (and will be set to an array / set).
There is one more problem - I am adding mappings before creating contexts, so I can't get entity... Trying use addConnectionForRelationship:connectedBy: method
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.