diff --git a/BWObjectMapping/BWObjectMapper.m b/BWObjectMapping/BWObjectMapper.m index b7a8268..beb7a1c 100644 --- a/BWObjectMapping/BWObjectMapper.m +++ b/BWObjectMapping/BWObjectMapper.m @@ -224,10 +224,15 @@ - (id)objectFromJSON:(id)JSON existingObject:(id)object { //////////////////////////////////////////////////////////////////////////////////////////////////// - (void)mapDictionary:(NSDictionary *)dict toObject:(id)object withMapping:(BWObjectMapping *)mapping { [mapping.attributeMappings enumerateKeysAndObjectsUsingBlock:^(id key, BWObjectAttributeMapping *attributeMapping, BOOL *stop) { - [[BWObjectValueMapper shared] setValue:[dict objectForKey:attributeMapping.keyPath] - forKeyPath:attributeMapping.attribute - withAttributeMapping:attributeMapping - forObject:object]; + + NSRange containsDotString = [attributeMapping.keyPath rangeOfString:@"."]; + if (containsDotString.location == NSNotFound) { + [self setValue:[dict objectForKey:attributeMapping.keyPath] forMapping:attributeMapping forObject:object]; + } else { + NSArray *keys = [attributeMapping.keyPath componentsSeparatedByString:@"."]; + [self setNestedValueForKeys:keys fromDictionary:dict forMapping:attributeMapping forObject:object]; + } + }]; if (nil != self.didMapObjectBlock) { @@ -235,5 +240,27 @@ - (void)mapDictionary:(NSDictionary *)dict toObject:(id)object withMapping:(BWOb } } +- (void)setValue:(NSString *)value forMapping:(BWObjectAttributeMapping *)attributeMapping forObject:(id)object +{ + [[BWObjectValueMapper shared] setValue:value + forKeyPath:attributeMapping.attribute + withAttributeMapping:attributeMapping + forObject:object]; +} + +- (void)setNestedValueForKeys:(NSArray *)keys fromDictionary:(NSDictionary *)dictionary forMapping:(BWObjectAttributeMapping *)attributeMapping forObject:(id)object +{ + id valuesContainer = dictionary; + id value; + for (NSInteger i = 0; i < [keys count]; i++) { + NSString *key = [keys objectAtIndex:i]; + if (i == ([keys count] -1 )) { + value = [valuesContainer objectForKey:key]; + } else { + valuesContainer = [valuesContainer objectForKey:key]; + } + } + [self setValue:value forMapping:attributeMapping forObject:object]; +} @end diff --git a/BWObjectMappingDemo.xcodeproj/project.pbxproj b/BWObjectMappingDemo.xcodeproj/project.pbxproj index 22e071e..272c985 100644 --- a/BWObjectMappingDemo.xcodeproj/project.pbxproj +++ b/BWObjectMappingDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + C69C256416D3F1C30008038E /* Person.m in Sources */ = {isa = PBXBuildFile; fileRef = C69C256316D3F1C30008038E /* Person.m */; }; E7018D4E15C6492600D3ADEE /* BWObjectValueMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = E7018D4D15C6492600D3ADEE /* BWObjectValueMapper.m */; }; E7018D5515C65FB000D3ADEE /* Entity.m in Sources */ = {isa = PBXBuildFile; fileRef = E7018D5415C65FB000D3ADEE /* Entity.m */; }; E7B6880F15BAA9E700002F08 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7B6880E15BAA9E700002F08 /* UIKit.framework */; }; @@ -42,6 +43,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + C69C256216D3F1C30008038E /* Person.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Person.h; sourceTree = ""; }; + C69C256316D3F1C30008038E /* Person.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Person.m; sourceTree = ""; }; E7018D4C15C6492600D3ADEE /* BWObjectValueMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWObjectValueMapper.h; sourceTree = ""; }; E7018D4D15C6492600D3ADEE /* BWObjectValueMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWObjectValueMapper.m; sourceTree = ""; }; E7018D5315C65FB000D3ADEE /* Entity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entity.h; sourceTree = ""; }; @@ -150,6 +153,8 @@ E7018D5315C65FB000D3ADEE /* Entity.h */, E7018D5415C65FB000D3ADEE /* Entity.m */, E7B6881715BAA9E700002F08 /* Supporting Files */, + C69C256216D3F1C30008038E /* Person.h */, + C69C256316D3F1C30008038E /* Person.m */, ); path = BWObjectMappingDemo; sourceTree = ""; @@ -314,6 +319,7 @@ E7B68A2A15BC98A100002F08 /* User.m in Sources */, E7018D4E15C6492600D3ADEE /* BWObjectValueMapper.m in Sources */, E7018D5515C65FB000D3ADEE /* Entity.m in Sources */, + C69C256416D3F1C30008038E /* Person.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/BWObjectMappingDemo/Person.h b/BWObjectMappingDemo/Person.h new file mode 100644 index 0000000..c1e89f2 --- /dev/null +++ b/BWObjectMappingDemo/Person.h @@ -0,0 +1,19 @@ +// +// Person.h +// BWObjectMappingDemo +// +// Created by Lucas Medeiros on 19/02/13. +// +// + +#import + +@interface Person : NSObject + +@property (nonatomic, copy) NSString *name; +@property (nonatomic, copy) NSString *email; +@property (nonatomic, copy) NSString *skype; +@property (nonatomic, strong) NSArray *phones; +@property (nonatomic, strong) NSDictionary *location; + +@end diff --git a/BWObjectMappingDemo/Person.m b/BWObjectMappingDemo/Person.m new file mode 100644 index 0000000..7bc0dc0 --- /dev/null +++ b/BWObjectMappingDemo/Person.m @@ -0,0 +1,13 @@ +// +// Person.m +// BWObjectMappingDemo +// +// Created by Lucas Medeiros on 19/02/13. +// +// + +#import "Person.h" + +@implementation Person + +@end diff --git a/BWObjectMappingDemoTests/BWObjectMapperSpecs.m b/BWObjectMappingDemoTests/BWObjectMapperSpecs.m index 3490e73..967b331 100644 --- a/BWObjectMappingDemoTests/BWObjectMapperSpecs.m +++ b/BWObjectMappingDemoTests/BWObjectMapperSpecs.m @@ -4,6 +4,7 @@ #import "User.h" #import "Comment.h" #import "Entity.h" +#import "Person.h" #import "AppDelegate.h" #define CUSTOM_VALUE_VALUE @"customValue" @@ -54,7 +55,7 @@ NSDictionary *JSON = [NSDictionary dictionaryWithObject:userJSON forKey:@"user"]; - NSArray *objects = [[BWObjectMapper shared] objectsFromJSON:JSON]; + NSArray *objects = [[BWObjectMapper shared] objectsFromJSON:JSON withObjectClass:[User class]]; User *user = [objects lastObject]; Class class = [[objects lastObject] class]; @@ -92,7 +93,7 @@ [JSON addObject:dict]; } - int objectCount = [[[BWObjectMapper shared] objectsFromJSON:JSON] count]; + int objectCount = [[[BWObjectMapper shared] objectsFromJSON:JSON withObjectClass:[User class]] count]; [[theValue(objectCount) should] equal:theValue(expectedNumberOfObjects)]; }); @@ -122,6 +123,75 @@ }); + context(@"Nested Attributes", ^{ + + __block Person *person; + __block NSDictionary *JSON; + + beforeAll(^{ + + [BWObjectMapping mappingForObject:[Person class] block:^(BWObjectMapping *mapping) { + [mapping mapKeyPath:@"name" toAttribute:@"name"]; + [mapping mapKeyPath:@"contact.email" toAttribute:@"email"]; + [mapping mapKeyPath:@"contact.others.skype" toAttribute:@"skype"]; + [mapping mapKeyPath:@"contact.phones" toAttribute:@"phones"]; + [mapping mapKeyPath:@"address.location" toAttribute:@"location"]; + [[BWObjectMapper shared] registerMapping:mapping withRootKeyPath:@"person"]; + }]; + + [[BWObjectMapper shared] objectWithBlock:^id(Class objectClass, NSString *primaryKey, id primaryKeyValue, id JSON) { + return [[objectClass alloc] init]; + }]; + + }); + + beforeEach(^{ + + JSON = @{ @"person" : @{ @"name" : @"Lucas", + @"contact" : @{ + @"email" : @"lucastoc@gmail.com", + @"phones" : @[ @"(12)1233-1333", @"(85)12331233" ], + @"others" : @{ @"skype" : @"aspmedeiros"} + }, + @"address" : @{ + @"location" : @{ @"lat": @(-18.123123123), @"long" : @(3.1123123123) } + } + } + }; + + person = [[BWObjectMapper shared] objectFromJSON:JSON withObjectClass:[Person class]]; + + }); + + specify(^{ + [[person should] beNonNil]; + }); + + specify(^{ + [[person.name should] equal:[[JSON objectForKey:@"person"] objectForKey:@"name"]]; + }); + + specify(^{ + [[person.email should] equal:[[[JSON objectForKey:@"person"] objectForKey:@"contact"] objectForKey:@"email"]]; + }); + + specify(^{ + [[person.skype should] equal:[[[[JSON objectForKey:@"person"] objectForKey:@"contact"] objectForKey:@"others"] objectForKey:@"skype"]]; + }); + + specify(^{ + int phonesCount = [person.phones count]; + int expectedPhoneCount = [[[[JSON objectForKey:@"person"] objectForKey:@"contact"] objectForKey:@"phones"] count]; + [[theValue(phonesCount) should] equal:theValue(expectedPhoneCount)]; + }); + + specify(^{ + [[person.location should] equal:[[[JSON objectForKey:@"person"] objectForKey:@"address"] objectForKey:@"location"]]; + }); + + + }); + context(@"Core data object", ^{ beforeAll(^{