diff --git a/EasyMapping.podspec b/EasyMapping.podspec index a4dfdc5..7515a6f 100644 --- a/EasyMapping.podspec +++ b/EasyMapping.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "EasyMapping" - s.version = "0.15.5" + s.version = "0.16.0" s.summary = "The easiest way to map data from your webservice." s.homepage = "https://github.com/lucasmedeirosleite/EasyMapping" diff --git a/EasyMapping/EKManagedObjectMapper.m b/EasyMapping/EKManagedObjectMapper.m index 01ff4bc..2c4ab4f 100644 --- a/EasyMapping/EKManagedObjectMapper.m +++ b/EasyMapping/EKManagedObjectMapper.m @@ -77,18 +77,26 @@ - (id)fillObject:(id)object fromExternalRepresentation:(NSDictionary *)externalR [mapping.hasOneMappings enumerateKeysAndObjectsUsingBlock:^(id key, EKRelationshipMapping * relationship, BOOL * stop) { NSDictionary * value = [relationship extractObjectFromRepresentation:representation]; - if (value) + if(mapping.ignoreMissingFields && (!value || value == (id)[NSNull null])) { - id result = nil; - if (value != (id)[NSNull null]) { - result = [self objectFromExternalRepresentation:value withMapping:(EKManagedObjectMapping *)[relationship objectMapping]]; - } - [EKPropertyHelper setValue:result onObject:object forKeyPath:relationship.property]; + return; + } + if (value && value != (id)[NSNull null]) { + id result = [self objectFromExternalRepresentation:value withMapping:(EKManagedObjectMapping *)[relationship objectMapping]]; + [EKPropertyHelper setValue:result onObject:object forKeyPath:relationship.property]; + } else { + [EKPropertyHelper setValue:nil onObject:object forKeyPath:relationship.property]; } + }]; [mapping.hasManyMappings enumerateKeysAndObjectsUsingBlock:^(id key, EKRelationshipMapping * relationship, BOOL * stop) { NSArray * arrayToBeParsed = [representation valueForKeyPath:key]; + if(mapping.ignoreMissingFields && (!arrayToBeParsed || arrayToBeParsed == (id)[NSNull null])) + { + return; + } + if (arrayToBeParsed && arrayToBeParsed != (id)[NSNull null]) { NSArray * parsedArray = [self arrayOfObjectsFromExternalRepresentation:arrayToBeParsed @@ -102,6 +110,8 @@ - (id)fillObject:(id)object fromExternalRepresentation:(NSDictionary *)externalR else { [EKPropertyHelper setValue:parsedObjects onObject:object forKeyPath:relationship.property]; } + } else { + [EKPropertyHelper setValue:nil onObject:object forKeyPath:relationship.property]; } }]; return object; diff --git a/EasyMapping/EKMapper.m b/EasyMapping/EKMapper.m index 2c7fea0..0355600 100644 --- a/EasyMapping/EKMapper.m +++ b/EasyMapping/EKMapper.m @@ -55,7 +55,7 @@ + (id)fillObject:(id)object fromExternalRepresentation:(NSDictionary *)externalR [mapping.hasOneMappings enumerateKeysAndObjectsUsingBlock:^(id key, EKRelationshipMapping * valueMapping, BOOL *stop) { NSDictionary * value = [valueMapping extractObjectFromRepresentation:representation]; - if(mapping.ignoreMissingFields && !value) + if(mapping.ignoreMissingFields && ((!value) || (value == (id)[NSNull null]))) { return; } diff --git a/EasyMappingExample/EasyMappingExample.xcodeproj/project.pbxproj b/EasyMappingExample/EasyMappingExample.xcodeproj/project.pbxproj index 6446dcc..46d8321 100644 --- a/EasyMappingExample/EasyMappingExample.xcodeproj/project.pbxproj +++ b/EasyMappingExample/EasyMappingExample.xcodeproj/project.pbxproj @@ -306,6 +306,7 @@ 9A53E2E61A7EA7F200C4D169 /* EKMappingBlocksSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A53E2E51A7EA7F200C4D169 /* EKMappingBlocksSpec.m */; }; 9A53E2E71A7EA7F200C4D169 /* EKMappingBlocksSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A53E2E51A7EA7F200C4D169 /* EKMappingBlocksSpec.m */; }; 9A7048131AB464A700EFD403 /* CarWithAttributesRemoved.json in Resources */ = {isa = PBXBuildFile; fileRef = 9EC0BF2C1AB35A1D00F584DF /* CarWithAttributesRemoved.json */; }; + 9A74F5401C85F2CE0063247E /* PersonWithoutRelations.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D612CB51C85DB8C00A167ED /* PersonWithoutRelations.json */; }; 9A8420DC19570689006DDDE3 /* BaseManagedTestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2056A41956E0EE00499FC3 /* BaseManagedTestModel.m */; }; 9A8420DD1957068A006DDDE3 /* BaseManagedTestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2056A41956E0EE00499FC3 /* BaseManagedTestModel.m */; }; 9A8420DE1957068D006DDDE3 /* BaseTestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2056A01956DF7900499FC3 /* BaseTestModel.m */; }; @@ -1309,6 +1310,7 @@ 9A210F3B1944B81500871071 /* PersonRecursive.json in Resources */, 9A45122819164705006E6022 /* CarWithNestedAttributes.json in Resources */, 9A45124419164705006E6022 /* PersonWithDifferentNaming.json in Resources */, + 9A74F5401C85F2CE0063247E /* PersonWithoutRelations.json in Resources */, 9AC0D8691A728D4C003926C1 /* PersonNonNested.json in Resources */, 9A45125019164705006E6022 /* Plane.json in Resources */, 9A45123C19164705006E6022 /* NativeChild.json in Resources */, diff --git a/EasyMappingExample/Tests/Specs/EKManagedObjectMappingSpec.m b/EasyMappingExample/Tests/Specs/EKManagedObjectMappingSpec.m index a107a54..5d928cf 100644 --- a/EasyMappingExample/Tests/Specs/EKManagedObjectMappingSpec.m +++ b/EasyMappingExample/Tests/Specs/EKManagedObjectMappingSpec.m @@ -10,8 +10,15 @@ #import "EasyMapping.h" #import "ManagedPerson.h" #import "ManagedCar.h" +#import "ManagedPhone.h" #import "ManagedMappingProvider.h" #import +#import "CMFixture.h" +#import +#import +#import +#import +#import SPEC_BEGIN(EKManagedObjectMappingSpec) @@ -385,6 +392,53 @@ }); + + describe(@"Supports ignore missing fields property", ^{ + + __block NSDictionary *externalRepresentation; + __block NSDictionary *externalRepresentationPartial; + __block EKManagedObjectMapping * personMapping; + __block NSManagedObjectContext* moc; + + beforeEach(^{ + [MagicalRecord setDefaultModelFromClass:[self class]]; + [MagicalRecord setupCoreDataStackWithInMemoryStore]; + + externalRepresentation = [CMFixture buildUsingFixture:@"Person"]; + externalRepresentationPartial = [CMFixture buildUsingFixture:@"PersonWithoutRelations"]; + moc = [NSManagedObjectContext MR_defaultContext]; + [ManagedPerson registerMapping:[ManagedMappingProvider personMapping]]; + [ManagedCar registerMapping:[ManagedMappingProvider carMapping]]; + [ManagedPhone registerMapping:[ManagedMappingProvider phoneMapping]]; + personMapping = [ManagedPerson objectMapping]; + }); + + specify(^{ + ManagedPerson *person = [EKManagedObjectMapper objectFromExternalRepresentation:externalRepresentation + withMapping:personMapping inManagedObjectContext:moc]; + + // Check default behaviour + [[person.car shouldNot] beNil]; + [[person.phones shouldNot] beNil]; + + [EKManagedObjectMapper fillObject:person fromExternalRepresentation:externalRepresentationPartial withMapping:personMapping inManagedObjectContext:moc]; + + [[person.car should] beNil]; + [[person.phones should] beEmpty]; + + // Check behaviour with set ignoreMissingFields property + person = [EKManagedObjectMapper objectFromExternalRepresentation:externalRepresentation + withMapping:personMapping inManagedObjectContext:moc]; + + personMapping.ignoreMissingFields = YES; + [[person.car shouldNot] beNil]; + [[person.phones shouldNot] beNil]; + [EKManagedObjectMapper fillObject:person fromExternalRepresentation:externalRepresentationPartial withMapping:personMapping inManagedObjectContext:moc]; + [[person.car shouldNot] beNil]; + [[person.phones shouldNot] beNil]; + }); + + }); }); SPEC_END