From 53cc6883e3939aa347284abf507b5bbac074a98e Mon Sep 17 00:00:00 2001 From: Aryan Date: Mon, 6 Apr 2015 14:40:50 -0700 Subject: [PATCH] Added ability to exclude keys from being added to dictionary when mapping model to dictionary #18 --- OCMapper.podspec | 4 +- .../In Code Mapping/InCodeMappingProvider.h | 8 ++++ .../In Code Mapping/InCodeMappingProvider.m | 12 ++++++ .../Source/Mapping Provider/MappingProvider.h | 1 + OCMapper/Source/ObjectMapper.m | 6 +++ OCMapperTests/ObjectMapperTests.m | 40 +++++++++++++++++++ 6 files changed, 69 insertions(+), 2 deletions(-) diff --git a/OCMapper.podspec b/OCMapper.podspec index 968173a..cfb0242 100644 --- a/OCMapper.podspec +++ b/OCMapper.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.platform = :ios, '5.0' s.name = 'OCMapper' - s.version = '1.5' + s.version = '1.6' s.summary = 'NSDictionary to NSObject Mapper' s.homepage = 'https://github.com/aryaxt/OCMapper' s.license = { @@ -9,7 +9,7 @@ Pod::Spec.new do |s| :file => 'License.txt' } s.author = {'Aryan Ghassemi' => 'https://github.com/aryaxt/OCMapper'} - s.source = {:git => 'https://github.com/aryaxt/OCMapper.git', :tag => '1.5'} + s.source = {:git => 'https://github.com/aryaxt/OCMapper.git', :tag => '1.6'} s.source_files = 'OCMapper/Source/*.{h,m}','OCMapper/Source/Categories/*.{h,m}','OCMapper/Source/Logging Provider/*.{h,m}','OCMapper/Source/Instance Provider/*.{h,m}','OCMapper/Source/Mapping Provider/*.{h,m}','OCMapper/Source/Mapping Provider/In Code Mapping/*.{h,m}','OCMapper/Source/Mapping Provider/PLIST Mapping/*.{h,m}','OCMapper/Source/Mapping Provider/XML Mapping/*.{h,m}' s.framework = 'Foundation' s.requires_arc = true diff --git a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h index f911dd5..c8a7318 100644 --- a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h +++ b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.h @@ -88,6 +88,14 @@ */ - (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class withTransformer:(MappingTransformer)transformer; +/** + * Set keys to be excluded when mapping model to a dictionary + * + * @param class Class to be assign mapping to + * @param keys NSArray of NSStrings, include properties to be excluded when mapping + */ +- (void)excludeMappingForClass:(Class)class withKeys:(NSArray *)keys; + /** * Set dateformatter to be used for converting a dictionary to a model object * diff --git a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m index 5ff118b..d53f3cf 100644 --- a/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m +++ b/OCMapper/Source/Mapping Provider/In Code Mapping/InCodeMappingProvider.m @@ -34,6 +34,7 @@ @interface InCodeMappingProvider() @property (nonatomic, strong) NSMutableDictionary *inverseMappingDictionary; @property (nonatomic, strong) NSMutableDictionary *dateFormatterDictionary; @property (nonatomic, strong) NSMutableDictionary *inverseDateFormatterDictionary; +@property (nonatomic, strong) NSMutableDictionary *excludeKeysDictionary; @end @implementation InCodeMappingProvider @@ -51,6 +52,7 @@ - (id)init self.inverseMappingDictionary = [NSMutableDictionary dictionary]; self.dateFormatterDictionary = [NSMutableDictionary dictionary]; self.inverseDateFormatterDictionary = [NSMutableDictionary dictionary]; + self.excludeKeysDictionary = [NSMutableDictionary dictionary]; } return self; @@ -94,6 +96,11 @@ - (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)d [self.inverseMappingDictionary setObject:info forKey:key]; } +- (void)excludeMappingForClass:(Class)class withKeys:(NSArray *)keys +{ + [self.excludeKeysDictionary setObject:keys forKey:NSStringFromClass(class)]; +} + - (void)setDateFormatter:(NSDateFormatter *)dateFormatter forPropertyKey:(NSString *)property andClass:(Class)class { NSString *key = [self uniqueKeyForClass:class andKey:property]; @@ -143,4 +150,9 @@ - (NSDateFormatter *)dateFormatterForClass:(Class)class andDictionaryKey:(NSStri return [self.dateFormatterDictionary objectForKey:key]; } +- (NSArray *)excludedKeysForClass:(Class)class +{ + return [self.excludeKeysDictionary objectForKey:NSStringFromClass(class)]; +} + @end diff --git a/OCMapper/Source/Mapping Provider/MappingProvider.h b/OCMapper/Source/Mapping Provider/MappingProvider.h index 880efd0..acf59f8 100644 --- a/OCMapper/Source/Mapping Provider/MappingProvider.h +++ b/OCMapper/Source/Mapping Provider/MappingProvider.h @@ -34,5 +34,6 @@ - (ObjectMappingInfo *)mappingInfoForClass:(Class)class andPropertyKey:(NSString *)key; - (NSDateFormatter *)dateFormatterForClass:(Class)class andPropertyKey:(NSString *)key; - (NSDateFormatter *)dateFormatterForClass:(Class)class andDictionaryKey:(NSString *)key; +- (NSArray *)excludedKeysForClass:(Class)class; @end diff --git a/OCMapper/Source/ObjectMapper.m b/OCMapper/Source/ObjectMapper.m index f7b94ad..7ad8d6a 100644 --- a/OCMapper/Source/ObjectMapper.m +++ b/OCMapper/Source/ObjectMapper.m @@ -182,11 +182,17 @@ - (id)processDictionaryFromObject:(NSObject *)object { unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(currentClass, &outCount); + NSArray *excludedKeys = [self.mappingProvider excludedKeysForClass:currentClass]; for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; NSString *originalPropertyName = [NSString stringWithUTF8String:property_getName(property)]; + + if (excludedKeys && [excludedKeys containsObject:originalPropertyName]) { + continue; + } + Class class = NSClassFromString([self typeForProperty:originalPropertyName andClass:[object class]]); id propertyValue = [object valueForKey:(NSString *)originalPropertyName]; diff --git a/OCMapperTests/ObjectMapperTests.m b/OCMapperTests/ObjectMapperTests.m index d229dac..5648739 100644 --- a/OCMapperTests/ObjectMapperTests.m +++ b/OCMapperTests/ObjectMapperTests.m @@ -454,6 +454,46 @@ - (void)testShouldNotAutomaticallyGenerateInverseMapping XCTAssertNil(info); } +- (void)testShouldMapArrayOfStringFromDictionaryToObject +{ + NSMutableDictionary *userDictionary = [NSMutableDictionary dictionary]; + [userDictionary setObject:@[@"keyword1", @2] forKey:@"randomKeywords"]; + + User *user = [self.mapper objectFromSource:userDictionary toInstanceOfClass:[User class]]; + XCTAssertTrue(user.randomKeywords.count == 2); + XCTAssertTrue([user.randomKeywords[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([user.randomKeywords[1] isEqualToNumber:@2]); +} + +- (void)testShouldMapArrayOfStringFromObjectToDictionary +{ + User *user = [[User alloc] init]; + user.randomKeywords = @[@"keyword1", @2].mutableCopy; + + NSDictionary *dictionary = [self.mapper dictionaryFromObject:user]; + NSArray *array = [dictionary objectForKey:@"randomKeywords"]; + + XCTAssertTrue(array.count == 2); + XCTAssertTrue([array[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([array[1] isEqualToNumber:@2]); +} + +- (void)testShouldNotMapExcludedKeys { + User *user = [[User alloc] init]; + user.firstName = @"f"; + user.lastName = @"l"; + user.age = @28; + user.dateOfBirth = [NSDate date]; + + [self.mappingProvider excludeMappingForClass:User.class withKeys:@[@"age", @"lastName"]]; + + NSDictionary *dictionary = [self.mapper dictionaryFromObject:user]; + XCTAssertNotNil(dictionary[@"firstName"]); + XCTAssertNotNil(dictionary[@"dateOfBirth"]); + XCTAssertNil(dictionary[@"age"]); + XCTAssertNil(dictionary[@"lastName"]); +} + - (void)testObjectInstanceProviderShouldReturnTrueForNSObjectSubclasses { XCTAssertTrue([self.instanceProvider canHandleClass:User.class]);