From d3017603c6b7966ea04b5f3c28f8ebd30c66dbef Mon Sep 17 00:00:00 2001 From: Denys Telezhkin Date: Fri, 1 Jul 2016 10:28:26 +0300 Subject: [PATCH] valueBlock should no longer be called if value in JSON is nil, and ignoreMissingFields property turned to YES. Fixes #126. --- EasyMapping/EKManagedObjectMapper.m | 3 ++- EasyMapping/EKMapper.m | 3 ++- EasyMapping/EKPropertyHelper.h | 9 ++++++--- EasyMapping/EKPropertyHelper.m | 12 ++++++++---- .../Classes/Providers/MappingProvider.h | 1 + .../Classes/Providers/MappingProvider.m | 19 +++++++++++++++++++ .../Tests/XCTests/EKMappingTestCase.m | 19 +++++++++++++++++++ 7 files changed, 57 insertions(+), 9 deletions(-) diff --git a/EasyMapping/EKManagedObjectMapper.m b/EasyMapping/EKManagedObjectMapper.m index e394ed8..3b9c562 100644 --- a/EasyMapping/EKManagedObjectMapper.m +++ b/EasyMapping/EKManagedObjectMapper.m @@ -72,7 +72,8 @@ - (id)fillObject:(id)object fromExternalRepresentation:(NSDictionary *)externalR onObject:object fromRepresentation:representation inContext:self.importer.context - respectPropertyType:mapping.respectPropertyFoundationTypes]; + respectPropertyType:mapping.respectPropertyFoundationTypes + ignoreMissingFields:mapping.ignoreMissingFields]; }]; [mapping.hasOneMappings enumerateKeysAndObjectsUsingBlock:^(id key, EKRelationshipMapping * relationship, BOOL * stop) { diff --git a/EasyMapping/EKMapper.m b/EasyMapping/EKMapper.m index 7ab7fce..0893d6b 100644 --- a/EasyMapping/EKMapper.m +++ b/EasyMapping/EKMapper.m @@ -50,7 +50,8 @@ + (id)fillObject:(id)object fromExternalRepresentation:(NSDictionary *)externalR [EKPropertyHelper setProperty:obj onObject:object fromRepresentation:representation - respectPropertyType:mapping.respectPropertyFoundationTypes]; + respectPropertyType:mapping.respectPropertyFoundationTypes + ignoreMissingFields:mapping.ignoreMissingFields]; }]; [mapping.hasOneMappings enumerateKeysAndObjectsUsingBlock:^(id key, EKRelationshipMapping * valueMapping, BOOL *stop) { NSDictionary * value = [valueMapping extractObjectFromRepresentation:representation]; diff --git a/EasyMapping/EKPropertyHelper.h b/EasyMapping/EKPropertyHelper.h index c80f8b4..1da6412 100644 --- a/EasyMapping/EKPropertyHelper.h +++ b/EasyMapping/EKPropertyHelper.h @@ -38,16 +38,19 @@ + (void) setProperty:(EKPropertyMapping *)propertyMapping onObject:(id)object fromRepresentation:(NSDictionary *)representation - respectPropertyType:(BOOL)respectPropertyType; + respectPropertyType:(BOOL)respectPropertyType + ignoreMissingFields:(BOOL)ignoreMissingFields; + (void) setProperty:(EKPropertyMapping *)propertyMapping onObject:(id)object fromRepresentation:(NSDictionary *)representation inContext:(NSManagedObjectContext *)context - respectPropertyType:(BOOL)respectPropertyType; + respectPropertyType:(BOOL)respectPropertyType + ignoreMissingFields:(BOOL)ignoreMissingFields; + (id)getValueOfProperty:(EKPropertyMapping *)propertyMapping - fromRepresentation:(NSDictionary *)representation; + fromRepresentation:(NSDictionary *)representation + ignoreMissingFields:(BOOL)ignoreMissingFields; + (id)getValueOfManagedProperty:(EKPropertyMapping *)mapping fromRepresentation:(NSDictionary *)representation diff --git a/EasyMapping/EKPropertyHelper.m b/EasyMapping/EKPropertyHelper.m index 27e7268..e1b84fe 100644 --- a/EasyMapping/EKPropertyHelper.m +++ b/EasyMapping/EKPropertyHelper.m @@ -96,9 +96,9 @@ + (id)propertyRepresentation:(id)value forObject:(id)object withPropertyName:(NS #pragma mark Property accessor methods + (void)setProperty:(EKPropertyMapping *)propertyMapping onObject:(id)object - fromRepresentation:(NSDictionary *)representation respectPropertyType:(BOOL)respectPropertyType + fromRepresentation:(NSDictionary *)representation respectPropertyType:(BOOL)respectPropertyType ignoreMissingFields:(BOOL)ignoreMIssingFields { - id value = [self getValueOfProperty:propertyMapping fromRepresentation:representation]; + id value = [self getValueOfProperty:propertyMapping fromRepresentation:representation ignoreMissingFields:ignoreMIssingFields]; if (value == (id)[NSNull null]) { if (![self propertyNameIsScalar:propertyMapping.property fromObject:object]) { [self setValue:nil onObject:object forKeyPath:propertyMapping.property]; @@ -118,6 +118,7 @@ + (void) setProperty:(EKPropertyMapping *)propertyMapping fromRepresentation:(NSDictionary *)representation inContext:(NSManagedObjectContext *)context respectPropertyType:(BOOL)respectPropertyType +ignoreMissingFields:(BOOL)ignoreMissingFields { id value = [self getValueOfManagedProperty:propertyMapping fromRepresentation:representation @@ -174,12 +175,15 @@ +(void)addValue:(id)value onObject:(id)object forKeyPath:(NSString *)keyPath } } -+ (id)getValueOfProperty:(EKPropertyMapping *)propertyMapping fromRepresentation:(NSDictionary *)representation ++ (id)getValueOfProperty:(EKPropertyMapping *)propertyMapping fromRepresentation:(NSDictionary *)representation ignoreMissingFields:(BOOL)ignoreMissingFields { id value = nil; if (propertyMapping.valueBlock) { - value = propertyMapping.valueBlock(propertyMapping.keyPath, [representation valueForKeyPath:propertyMapping.keyPath]); + value = [representation valueForKeyPath:propertyMapping.keyPath]; + if (value != nil || !ignoreMissingFields) { + value = propertyMapping.valueBlock(propertyMapping.keyPath, value); + } } else { value = [representation valueForKeyPath:propertyMapping.keyPath]; diff --git a/EasyMappingExample/Classes/Providers/MappingProvider.h b/EasyMappingExample/Classes/Providers/MappingProvider.h index 73743fd..3edaa99 100644 --- a/EasyMappingExample/Classes/Providers/MappingProvider.h +++ b/EasyMappingExample/Classes/Providers/MappingProvider.h @@ -24,5 +24,6 @@ + (EKObjectMapping *)personWithRelativeMapping; + (EKObjectMapping *)addressMapping; + (EKObjectMapping *)nativeMappingWithNullPropertie; ++ (EKObjectMapping *)personMappingThatAssertsOnNilInValueBlock; @end diff --git a/EasyMappingExample/Classes/Providers/MappingProvider.m b/EasyMappingExample/Classes/Providers/MappingProvider.m index 3bbebdb..d42ca00 100644 --- a/EasyMappingExample/Classes/Providers/MappingProvider.m +++ b/EasyMappingExample/Classes/Providers/MappingProvider.m @@ -112,6 +112,25 @@ + (EKObjectMapping *)personMapping }]; } ++(EKObjectMapping *)personMappingThatAssertsOnNilInValueBlock +{ + return [EKObjectMapping mappingForClass:[Person class] withBlock:^(EKObjectMapping *mapping) { + NSDictionary *genders = @{ @"male": @(GenderMale), @"female": @(GenderFemale) }; + [mapping mapPropertiesFromArray:@[@"name", @"email"]]; + [mapping mapKeyPath:@"gender" toProperty:@"gender" withValueBlock:^(NSString *key, id value) { + if (value == nil) { [[[NSException alloc] initWithName:@"Received nil value" reason:@"In value block when ignore missing fields is turned on" userInfo:nil] raise]; } + return genders[value]; + } reverseBlock:^id(id value) { + return [genders allKeysForObject:value].lastObject; + }]; + [mapping hasOne:[Car class] forKeyPath:@"car"]; + [mapping hasMany:[Phone class] forKeyPath:@"phones"]; + [mapping mapKeyPath:@"socialURL" toProperty:@"socialURL" + withValueBlock:[EKMappingBlocks urlMappingBlock] + reverseBlock:[EKMappingBlocks urlReverseMappingBlock]]; + }]; +} + + (EKObjectMapping *)personWithCarMapping { return [EKObjectMapping mappingForClass:[Person class] withBlock:^(EKObjectMapping *mapping) { diff --git a/EasyMappingExample/Tests/XCTests/EKMappingTestCase.m b/EasyMappingExample/Tests/XCTests/EKMappingTestCase.m index accc52b..05a3f6a 100644 --- a/EasyMappingExample/Tests/XCTests/EKMappingTestCase.m +++ b/EasyMappingExample/Tests/XCTests/EKMappingTestCase.m @@ -138,4 +138,23 @@ - (void)testIgnoreMissingFieldsProperty XCTAssertNotNil(person.phones); } +- (void) testIgnoreMissingFieldsWorksForProperties { + NSDictionary *externalRepresentation = [CMFixture buildUsingFixture:@"Person"]; + + [Person registerMapping:[MappingProvider personMappingThatAssertsOnNilInValueBlock]]; + [Car registerMapping:[MappingProvider carMapping]]; + [Phone registerMapping:[MappingProvider phoneMapping]]; + EKObjectMapping *personMapping = [Person objectMapping]; + + Person *person = [EKMapper objectFromExternalRepresentation:externalRepresentation + withMapping:personMapping]; + + personMapping.ignoreMissingFields = YES; + XCTAssertNotNil(person.car); + XCTAssertNotNil(person.phones); + [EKMapper fillObject:person fromExternalRepresentation:@{@"id":@23,@"name":@"Lucas"} withMapping:personMapping]; + XCTAssert(person.gender == GenderMale); + XCTAssert([person.socialURL.absoluteString isEqual:@"https://www.twitter.com/EasyMapping"]); +} + @end