From 07d6d7442594577bbb0a65a33f38cab30811c478 Mon Sep 17 00:00:00 2001 From: Denys Telezhkin Date: Fri, 1 Jul 2016 18:13:46 +0300 Subject: [PATCH] implement method for converting underscore properties to camel case. Bump podspec. --- EasyMapping.podspec | 2 +- EasyMapping/EKObjectMapping.h | 11 +++- EasyMapping/EKObjectMapping.m | 10 ++++ EasyMapping/EKPropertyHelper.h | 2 + EasyMapping/EKPropertyHelper.m | 17 ++++++ .../NSDateFormatter+EasyMappingAdditions.h | 2 +- .../Tests/Specs/EKObjectMappingSpec.m | 54 +++++++++++++++++++ 7 files changed, 94 insertions(+), 4 deletions(-) diff --git a/EasyMapping.podspec b/EasyMapping.podspec index 4233a03..18f3bb8 100644 --- a/EasyMapping.podspec +++ b/EasyMapping.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EasyMapping" - s.version = "0.17.1" + s.version = "0.18.0" s.summary = "The easiest way to map data from your webservice." s.homepage = "https://github.com/lucasmedeirosleite/EasyMapping" s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/EasyMapping/EKObjectMapping.h b/EasyMapping/EKObjectMapping.h index f4f8483..638380c 100644 --- a/EasyMapping/EKObjectMapping.h +++ b/EasyMapping/EKObjectMapping.h @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN /** Root JSON path. This is helpful, when all object data is inside another JSON dictionary. */ -@property (nonatomic, strong, readonly) NSString *rootPath; +@property (nonatomic, strong, readonly, nullable) NSString *rootPath; /** Dictionary, containing property mappings for current object. @@ -131,7 +131,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)mapKeyPath:(NSString *)keyPath toProperty:(NSString *)property; /** - Map JSON keyPath to object property. This method assumes, that value contains NSString, that can be transformed into NSDate by NSDateFormatter. You can get current thread date formatter by using NSDateFormatter+EasyMappingAdditions category. Default timezone is GMT. Default date format ISO 8601. + Map JSON keyPath to object property. This method assumes, that value contains NSString, that can be transformed into NSDate by NSDateFormatter. @param keyPath JSON keypath, that will be used by valueForKeyPath: method @@ -155,6 +155,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)mapPropertiesFromArrayToPascalCase:(NSArray *)propertyNamesArray; +/** + Maps properties from array, making all keypaths that contain underscores - camel cased. For example, @"created_at" field in JSON will be mapped to @"createdAt" property on your model. + + @param propertyNamesArray Array of property names. + */ +- (void)mapPropertiesFromUnderscoreToCamelCase:(NSArray *)propertyNamesArray; + /** Maps properties from dictionary. Keys are keypaths in JSON, values are names of properties. diff --git a/EasyMapping/EKObjectMapping.m b/EasyMapping/EKObjectMapping.m index 0cb7d84..9f44374 100644 --- a/EasyMapping/EKObjectMapping.m +++ b/EasyMapping/EKObjectMapping.m @@ -26,6 +26,7 @@ #import "EKRelationshipMapping.h" #import "EKMappingProtocol.h" #import "NSDateFormatter+EasyMappingAdditions.h" +#import "EKpropertyHelper.h" @implementation EKObjectMapping @@ -119,6 +120,15 @@ -(void)mapPropertiesFromArrayToPascalCase:(NSArray *)propertyNamesArray } } +- (void)mapPropertiesFromUnderscoreToCamelCase:(NSArray *)propertyNamesArray +{ + for (NSString *key in propertyNamesArray) { + NSString *convertedKey = [EKPropertyHelper convertStringFromUnderScoreToCamelCase: key]; + + [self mapKeyPath:key toProperty:convertedKey]; + } +} + - (void)mapPropertiesFromDictionary:(NSDictionary *)propertyDictionary { NSParameterAssert([propertyDictionary isKindOfClass:[NSDictionary class]]); diff --git a/EasyMapping/EKPropertyHelper.h b/EasyMapping/EKPropertyHelper.h index a665784..9800e30 100644 --- a/EasyMapping/EKPropertyHelper.h +++ b/EasyMapping/EKPropertyHelper.h @@ -65,6 +65,8 @@ NS_ASSUME_NONNULL_BEGIN + (nullable NSDictionary *)extractRootPathFromExternalRepresentation:(NSDictionary *)externalRepresentation withMapping:(EKObjectMapping *)mapping; ++ (NSString *)convertStringFromUnderScoreToCamelCase:(NSString *)string; + @end NS_ASSUME_NONNULL_END diff --git a/EasyMapping/EKPropertyHelper.m b/EasyMapping/EKPropertyHelper.m index e1b84fe..bbcf337 100644 --- a/EasyMapping/EKPropertyHelper.m +++ b/EasyMapping/EKPropertyHelper.m @@ -217,4 +217,21 @@ + (NSDictionary *)extractRootPathFromExternalRepresentation:(NSDictionary *)exte } return externalRepresentation; } + ++ (NSString *)convertStringFromUnderScoreToCamelCase:(NSString *)string { + NSMutableString *output = [NSMutableString string]; + BOOL makeNextCharacterUpperCase = NO; + for (NSInteger idx = 0; idx < [string length]; idx += 1) { + unichar c = [string characterAtIndex:idx]; + if (c == '_') { + makeNextCharacterUpperCase = YES; + } else if (makeNextCharacterUpperCase) { + [output appendString:[[NSString stringWithCharacters:&c length:1] uppercaseString]]; + makeNextCharacterUpperCase = NO; + } else { + [output appendFormat:@"%C", c]; + } + } + return output; +} @end diff --git a/EasyMapping/NSDateFormatter+EasyMappingAdditions.h b/EasyMapping/NSDateFormatter+EasyMappingAdditions.h index c508d9a..d551567 100644 --- a/EasyMapping/NSDateFormatter+EasyMappingAdditions.h +++ b/EasyMapping/NSDateFormatter+EasyMappingAdditions.h @@ -42,7 +42,7 @@ static NSString * const EKISO_8601DateTimeFormat = @"yyyy-MM-dd"; /** NSDateFormatter instance for current NSThread. It is lazily constructed, default date format - ISO 8601. - Thos property is deprecated and stated to be removed in release for Xcode 8, which drops support for iOS 7 and lower. + Thos property is deprecated and slated to be removed in release for Xcode 8, which drops support for iOS 7 and lower. */ + (NSDateFormatter *)ek_formatterForCurrentThread DEPRECATED_ATTRIBUTE; diff --git a/EasyMappingExample/Tests/Specs/EKObjectMappingSpec.m b/EasyMappingExample/Tests/Specs/EKObjectMappingSpec.m index 0a2b821..c715c40 100644 --- a/EasyMappingExample/Tests/Specs/EKObjectMappingSpec.m +++ b/EasyMappingExample/Tests/Specs/EKObjectMappingSpec.m @@ -359,6 +359,60 @@ }); + describe(@"#mapPropertiesFromUnderscoreToCamelCase", ^{ + + __block EKObjectMapping *mapping; + + beforeEach(^{ + mapping = [[EKObjectMapping alloc] initWithObjectClass:[Car class]]; + [mapping mapPropertiesFromUnderscoreToCamelCase:@[@"model", @"year", @"created_at",@"car_id"]]; + }); + + describe(@"createdAt field", ^{ + + __block EKPropertyMapping *propertyMapping; + + beforeEach(^{ + propertyMapping = [mapping.propertyMappings objectForKey:@"created_at"]; + }); + + specify(^{ + [[propertyMapping shouldNot] beNil]; + }); + + specify(^{ + [[propertyMapping.keyPath should] equal:@"created_at"]; + }); + + specify(^{ + [[propertyMapping.property should] equal:@"createdAt"]; + }); + }); + + describe(@"car_id field", ^{ + + __block EKPropertyMapping *propertyMapping; + + beforeEach(^{ + propertyMapping = [mapping.propertyMappings objectForKey:@"car_id"]; + }); + + specify(^{ + [[propertyMapping shouldNot] beNil]; + }); + + specify(^{ + [[propertyMapping.keyPath should] equal:@"car_id"]; + }); + + specify(^{ + [[propertyMapping.property should] equal:@"carId"]; + }); + + }); + + }); + describe(@"#mapPropertiesFromDictionary", ^{