I have the following JSON body containing arrays of decimal numbers within arrays:
( I. )
{
"decimals":
[
[
18000.00,
18000.00
]
],
}
I have created a class DecimalEntity
with helper attribute "number
" (NSDecimalNumber
) and recursive relationship "numbers
" (1-many relationship). Also this variant is possible:
( II. )
{
"decimals":
[
18000.00,
18000.00
],
}
How can I setup the mapping of the DecimalEntity
so that it parses the above JSON
bodies? I have setup the property mapping for "number
" which works for (II.) but it does not work for (I.) That is why I've created the relationship between the DecimalEntity
and "numbers
" using
RKPropertyMapping* decimalEntityPropertyMapping =
[RKRelationshipMapping relationshipMappingFromKeyPath:nil
toKeyPath:@"numbers"
withMapping:decimalEntityMapping];
and added this decimalEntityPropertyMapping
back in decimalEntityMapping
to create a recursive relationship:
[decimalEntityMapping addPropertyMapping:decimalEntityPropertyMapping];
But this variant crashes with **[NSNull hasPrefix:]:
unrecognized selector sent to instance**
Also I tried to flatten the arrays using @unionOfArrays
but I do not know how to use it.
[mapping addAttributeMappingsFromDictionary:@{@"@unionOfArrays": @"numbers" }];
?
Thank you for a hint.
I'm trying to do it in a conventional way, because it should work I think. I have changed the structure and the relationship of my classes (NSManagedObject subclasses):
DecimalEntityArray: contains a helper relationship 1-M to DecimalEntity's:"decimals"
DecimalEntity: contains a helper attribute of the type Decimal: "number"
The class DecimalEntityArray is mapped to the outer brackets and the DecimalEntity to inner brackets:
"arrayOfArrays":
[ >>>>> 1-M, DecimalEntityArray
[ >>>>> 1-M, DecimalEntity
18000.00,
18000.00
]
],
Mapping setup looks like this:
// setting up the attribute mappings:
RKObjectMapping* decimalEntityMapping =
[DecimalEntity mappingForStore:managedObjectStore];
RKObjectMapping* decimalEntityArrayMapping =
[DecimalEntityArray mappingForStore:managedObjectStore];
// the **nil** value denotes the fact that there is no dictionary,
// just a direct mapping to NSSet of DecimalEntity's
RKPropertyMapping* decimalEntityPropertyMapping =
[RKRelationshipMapping relationshipMappingFromKeyPath:nil
toKeyPath:@"decimals"
withMapping:decimalEntityMapping];
// setup the relationship between DecimalEntityArray and its DecimalEntity's
[decimalEntityArrayMapping addPropertyMapping:decimalEntityPropertyMapping];
// finally setup the relation between the outermost json attribute, "arrayOfArrays"
// and DecimalEntityArray
RKPropertyMapping* decimalEntityArrayPropertyMappingPotentialWin =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"potentionalWin"
toKeyPath:@"potentionalWin"
withMapping:decimalEntityArrayMapping];
But this solution crashes with [NSNull hasPrefix:]: unrecognized selector sent to instance and a suggestion
Mapping one to many relationship value at keyPath 'arrayOfArrays' to 'arrayOfArrays' ... WARNING: Detected a relationship mapping for a collection containing another collection. This is probably not what you want. Consider using a KVC collection operator (such as @unionOfArrays) to flatten your mappable collection.
This is probably not what you want. But that is really what I want. So this conventional way does not work? I guess I am a step from getting it correct.
[NSNull hasPrefix:]: unrecognized selector sent to instance originates from the definition of decimalEntityPropertyMapping, where the KeyPath == nil. The strange thing is the nil value is allowed according the documentation:
sourceKeyPath:
A key path from which to retrieve data in the source object representation that is to be mapped as a relationship. If nil
, then the mapping is performed directly against the parent object representation.
I have checked the issue with debugger (adding symbolic exception with the symbol -[NSObject doesNotRecognizeSelector:]) and added the line if([keyPath isKindOfClass:[NSNull class]]) return YES; in RKMappingOperation.m and it works smoothly with the above mapping defined:
// Returns YES if there is a value present for at least one key path in the given collection
static BOOL RKObjectContainsValueForKeyPaths(id representation, NSArray *keyPaths)
{
for (NSString *keyPath in keyPaths) {
if([keyPath isKindOfClass:[NSNull class]]) return YES;
if ([representation valueForKeyPath:keyPath]) return YES;
}
return NO;
}