diff --git a/CSMapperTestApp/CSMapperTestApp.xcodeproj/project.xcworkspace/xcshareddata/CSMapperTestApp.xccheckout b/CSMapperTestApp/CSMapperTestApp.xcodeproj/project.xcworkspace/xcshareddata/CSMapperTestApp.xccheckout index a09fd2a..f601a31 100644 --- a/CSMapperTestApp/CSMapperTestApp.xcodeproj/project.xcworkspace/xcshareddata/CSMapperTestApp.xccheckout +++ b/CSMapperTestApp/CSMapperTestApp.xcodeproj/project.xcworkspace/xcshareddata/CSMapperTestApp.xccheckout @@ -10,29 +10,29 @@ CSMapperTestApp IDESourceControlProjectOriginsDictionary - 58B62EAD-450F-433B-9448-4E0A05497FBF - ssh://github.com/marcammann/CSMapper.git + 7B4F58B70F1D66ED172BF588CBF60BF38A1FA730 + github.com:AntonTheDev/CSMapper.git IDESourceControlProjectPath - CSMapperTestApp/CSMapperTestApp.xcodeproj/project.xcworkspace + CSMapperTestApp/CSMapperTestApp.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary - 58B62EAD-450F-433B-9448-4E0A05497FBF + 7B4F58B70F1D66ED172BF588CBF60BF38A1FA730 ../../.. IDESourceControlProjectURL - ssh://github.com/marcammann/CSMapper.git + github.com:AntonTheDev/CSMapper.git IDESourceControlProjectVersion - 110 + 111 IDESourceControlProjectWCCIdentifier - 58B62EAD-450F-433B-9448-4E0A05497FBF + 7B4F58B70F1D66ED172BF588CBF60BF38A1FA730 IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - 58B62EAD-450F-433B-9448-4E0A05497FBF + 7B4F58B70F1D66ED172BF588CBF60BF38A1FA730 IDESourceControlWCCName CSMapper diff --git a/Classes/NSObject+CSAPI.m b/Classes/NSObject+CSAPI.m index ad67e19..42a3d75 100644 --- a/Classes/NSObject+CSAPI.m +++ b/Classes/NSObject+CSAPI.m @@ -20,6 +20,7 @@ static NSString * const CSMappingClassKey = @"type"; static NSString * const CSMappingGroupsKey = @"groups"; static NSString * const CSMappingArraySubTypeKey = @"array_subtype"; +static NSString * const CSMappingCollectionSubTypeKey = @"collection_subtype"; static NSString * const CSMappingMapperKey = @"mapper"; static NSString * const CSMappingDefaultKey = @"default"; @@ -155,7 +156,7 @@ - (void)mapAttributesWithDictionary:(NSDictionary *)aDictionary groups:(NSArray selector = NSSelectorFromString([NSString stringWithFormat:@"%@Value", forcedClass]); if ([inputValue respondsToSelector:selector]) { // Try to use the built in conversion features for known types - outputValue = objc_msgSend(inputValue, selector); + outputValue = ((id (*)(id, SEL))objc_msgSend)(inputValue, selector); } else { // Try to map unknown type with same technique. id newValue = [[forcedClass alloc] init]; @@ -165,26 +166,46 @@ - (void)mapAttributesWithDictionary:(NSDictionary *)aDictionary groups:(NSArray } //check to see if there is a type for the objects in an array - arraySubTypeValue = [propertyMapping objectForKey:CSMappingArraySubTypeKey]; - - if ([inputValue isKindOfClass:[NSArray class]] && arraySubTypeValue) { + arraySubTypeValue = [propertyMapping objectForKey:CSMappingCollectionSubTypeKey]; + + if(!arraySubTypeValue) + { + // Backwards compatibility prior to the addition of dictionary type mapping + arraySubTypeValue = [propertyMapping objectForKey:CSMappingArraySubTypeKey]; + } + + if (arraySubTypeValue) { forcedClassString = arraySubTypeValue; forcedClass = NSClassFromString(arraySubTypeValue); NSMutableArray *newSubObjectArray = [NSMutableArray new]; - - for (id subobjectDict in inputValue) { - id newValue = [[forcedClass alloc] init]; - [newValue mapAttributesWithDictionary:subobjectDict]; - [newSubObjectArray addObject:newValue]; + + if ([inputValue isKindOfClass:[NSArray class]] ){ + for (id subobjectDict in inputValue) { + id newValue = [[forcedClass alloc] init]; + [newValue mapAttributesWithDictionary:subobjectDict]; + [newSubObjectArray addObject:newValue]; + } + } else if ([inputValue isKindOfClass:[NSDictionary class]] ){ + for (id subobjectDict in [inputValue allValues]) { + id newValue = [[forcedClass alloc] init]; + [newValue mapAttributesWithDictionary:subobjectDict]; + [newSubObjectArray addObject:newValue]; + } } + outputValue = newSubObjectArray; } - + if (mapperClass && mapperClass) { outputValue = [(id)mapperClass transformValue:inputValue]; } + if([propertyName isEqualToString:@"subDictionaryValue"]) + { + NSLog(@"STOP"); + } + [self setValue:outputValue forKey:propertyName]; } } @@ -251,12 +272,10 @@ - (NSNumber *)NSNumberValue { return (NSNumber *)self; } else { - return nil; } } - /** Converts an object into an NSString */ diff --git a/Tests/CSAPIMapperTests.m b/Tests/CSAPIMapperTests.m index 3b7c948..b9be05a 100644 --- a/Tests/CSAPIMapperTests.m +++ b/Tests/CSAPIMapperTests.m @@ -52,6 +52,8 @@ @interface TestTestObject : NSObject @property (nonatomic, readwrite) BOOL falseBool; @property (nonatomic, strong) NSString *subSubValue; @property (nonatomic, strong) NSArray *subArrayValue; +@property (nonatomic, strong) NSArray *subDictionaryValue; +@property (nonatomic, strong) NSArray *subArrayLegacyValue; @end @@ -211,16 +213,36 @@ - (void)testCompoundSubtype } -- (void)testArraySubtype +- (void)testCollectionAsDictionarySubtype +{ + TestTestObject *o = [[TestTestObject alloc] init]; + + [o mapAttributesWithDictionary:@{ @"test_subdictionary" : @{@"Object1" : @{@"test_trivial" : @"Test1"}, @"Object2" : @{@"test_trivial" : @"Test2"}, @"Object3" : @{@"test_trivial" : @"Test3"}}}]; + + STAssertEqualObjects([[o.subDictionaryValue objectAtIndex:0] testTrivial], @"Test1", @"1"); + STAssertEqualObjects([[o.subDictionaryValue objectAtIndex:1] testTrivial], @"Test2", @"2"); + STAssertEqualObjects([[o.subDictionaryValue objectAtIndex:2] testTrivial], @"Test3", @"3"); +} + + +- (void)testCollectionAsArraySubtype { TestTestObject *o = [[TestTestObject alloc] init]; [o mapAttributesWithDictionary:@{ @"test_subarray" : @[ @{@"test_trivial" : @"Test1"}, @{@"test_trivial" : @"Test2"}, @{@"test_trivial" : @"Test3"}] }]; + STAssertEqualObjects([[o.subArrayValue objectAtIndex:0] testTrivial], @"Test1", @"1"); + STAssertEqualObjects([[o.subArrayValue objectAtIndex:1] testTrivial], @"Test2", @"2"); + STAssertEqualObjects([[o.subArrayValue objectAtIndex:2] testTrivial], @"Test3", @"3"); +} + +- (void)testCollectionAsLegacyArraySubtype +{ + TestTestObject *o = [[TestTestObject alloc] init]; + [o mapAttributesWithDictionary:@{ @"test_subarray" : @[ @{@"test_trivial" : @"Test1"}, @{@"test_trivial" : @"Test2"}, @{@"test_trivial" : @"Test3"}] }]; STAssertEqualObjects([[o.subArrayValue objectAtIndex:0] testTrivial], @"Test1", nil); STAssertEqualObjects([[o.subArrayValue objectAtIndex:1] testTrivial], @"Test2", nil); STAssertEqualObjects([[o.subArrayValue objectAtIndex:2] testTrivial], @"Test3", nil); } - - (void)testJsonMapping { TestJsonMappedObject *o = [TestJsonMappedObject new]; diff --git a/Tests/TestTestObject.plist b/Tests/TestTestObject.plist index d19de79..9523b2e 100644 --- a/Tests/TestTestObject.plist +++ b/Tests/TestTestObject.plist @@ -92,6 +92,24 @@ subArrayValue + + type + NSArray + key + test_subarray + collection_subtype + TestTestSubtype + + subDictionaryValue + + type + NSDictionary + key + test_subdictionary + collection_subtype + TestTestSubtype + + subArrayLegacyValue type NSArray