0
votes

I'm using RestKit v0.21 and trying to map an array of values with dynamic names. I'm able to get the names of the custom fields correctly, but I'm not able to capture the associated values. The JSON looks like this:

{
    "id": 1,
    "firstName": "Kenny",
    "lastName": "Powers",
    "customFields": {
        "favorite color": "blue",
        "hometown": "Cleveland",
        "spouse name": "sally"
    }
}

My mappings look like this:

//PERSON MAPPING
RKEntityMapping *personMapping = [RKEntityMapping mappingForEntityForName:@"Person" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
[personMapping addAttributeMappingsFromDictionary:@{
                                                     @"id":             @"personId",
                                                     @"firstName":      @"firstName",
                                                     @"lastName":       @"lastName"}];
personMapping.identificationAttributes = @[ @"personId" ];

//CUSTOM FIELD MAPPING
RKEntityMapping *customFieldMapping = [RKEntityMapping mappingForEntityForName:@"CustomValue" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
customFieldMapping.forceCollectionMapping = YES;
[customFieldMapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"fieldName"];
[customFieldMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"(fieldName)" toKeyPath:@"fieldValue"]];

[personMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"customFields"
                                                                             toKeyPath:@"customValues"
                                                                           withMapping:customFieldMapping]];

All of the examples I've seen with Dynamic attributes involve an object of values, where the value mapping would be like "(fileName).email". In my case it's always just a string:string set of names and values that represent a completely dynamic set of custom fields and accompanying values.

When I inspect the collection of custom field objects the fieldName property is set but the fieldValue properties are all (null).

Any ideas?

UPDATE: Here's the log output for one of the mappings for the elements in the array of custom fields:

2013-10-11 09:54:45.558 MyMobile[45460:6207] D restkit.object_mapping:RKMappingOperation.m:851 Starting mapping operation...
2013-10-11 09:54:45.558 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:852 Performing mapping operation: <RKMappingOperation 0x17a71230> for 'CustomValue' object. Mapping values from object {
    "Youtube Link" = "http://www.youtube.com";
} to object <CustomValue: 0xac42b00> (entity: CustomValue; id: 0xac69420 <x-coredata://D54F8070-D653-49E2-AFD5-90CD9778B2D4/CustomValue/p3> ; data: {
    fieldName = "Youtube Link";
    fieldValue = nil;
    person = "0x16f8d200 <x-coredata://D54F8070-D653-49E2-AFD5-90CD9778B2D4/Person/p389>";
}) with object mapping (null)
2013-10-11 09:54:45.559 MyMobile[45460:6207] D restkit.object_mapping:RKMappingOperation.m:813 Found nested mapping definition to attribute 'fieldName'
2013-10-11 09:54:45.560 MyMobile[45460:6207] D restkit.object_mapping:RKMappingOperation.m:816 Found nesting value of 'Youtube Link' for attribute 'fieldName'
2013-10-11 09:54:45.562 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:440 Mapping attribute value keyPath '<RK_NESTING_ATTRIBUTE>' to 'fieldName'
2013-10-11 09:54:45.562 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:429 Found transformable value at keyPath '<RK_NESTING_ATTRIBUTE>'. Transforming from class '__NSCFString' to 'NSString'
2013-10-11 09:54:45.563 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:475 Skipped mapping of attribute value from keyPath '<RK_NESTING_ATTRIBUTE> to keyPath 'fieldName' -- value is unchanged (Youtube Link)
2013-10-11 09:54:45.564 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:497 Skipping attribute mapping for special keyPath '<RK_NESTING_ATTRIBUTE>'
2013-10-11 09:54:45.564 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:440 Mapping attribute value keyPath 'Youtube Link' to 'fieldValue'
2013-10-11 09:54:45.565 MyMobile[45460:6207] T restkit.object_mapping:RKMappingOperation.m:429 Found transformable value at keyPath 'Youtube Link'. Transforming from class '__NSCFString' to 'NSString'
2013-10-11 09:54:45.565 MyMobile[45460:6207] E restkit.object_mapping:RKMappingOperation.m:431 Failed transformation of value at keyPath 'Youtube Link' to representation of type 'NSString': (null)
2013-10-11 09:54:45.566 MyMobile[45460:6207] D restkit.object_mapping:RKMappingOperation.m:920 Finished mapping operation successfully...
1
Don't know if it will work but you could try attributeMappingFromKeyPath:nil toKeyPath:@"fieldValue". Need to step through the mapping process to see what data is available... - Wain
I tried that: [customFieldMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"fieldValue"]]; But it didn't many any difference. Whereabouts in the source code of the mapping process would be a good place to look when stepping through? - scubasteve
Turn on trace logging for the mapping and look to debug through RKMappingOperation.m - Wain
I updated my original question with the log details. Anything jump out at you? - scubasteve
Not really. I'm not sure you can do it directly with mappings. The RestKit API is based around extracting each of the unknown keys in the dictionary into a single object. I think it's the forced collection mapping that is mixing everything up. - Wain

1 Answers

1
votes

I ran into a similar issue recently. It seems that the value transformer isn't initialised correctly sometimes when using dynamic attribute mapping.

I found a workaround by changing the property from NSString to type id within my NSManagedObject subclass. For example, say your NSManagedObject normally looks like this:

@interface CustomValue : NSManagedObject

@property (nonatomic, retain) NSString * fieldValue;

@end

try changing this to:

@interface CustomValue : NSManagedObject

@property (nonatomic, retain) id fieldValue;

@end

You'll also have to change your fieldValue within your data model from String to Transformable.

After I did this, the mapping still converted the type into an NSString but it was successful.