From 222c46dcdd104e1affd80e630f307619acc80a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=AF=E7=A3=8A?= Date: Thu, 23 Jun 2016 21:52:57 +0800 Subject: [PATCH 1/3] add modelCustomPropertyForPropertyName method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 方便具有一定规则的自定义属性名,使用该方法不用一一列举属性名。如:JSON键名首字母都是大写,本地声名的模型首字母都是小写。 --- README.md | 95 ++++++++++++++++++++++------ YYModel/NSObject+YYModel.h | 46 ++++++++++++++ YYModel/NSObject+YYModel.m | 105 +++++++++++++++++-------------- YYModelTests/YYTestModelMapper.m | 52 +++++++++++---- 4 files changed, 218 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index ea38047..9be3af2 100755 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ Usage @implementation User @end - + // Convert json to model: User *user = [User yy_modelWithJSON:json]; - + // Convert model to json: NSDictionary *json = [user yy_modelToJSONObject]; @@ -147,6 +147,33 @@ EEE MMM dd HH:mm:ss Z yyyy } @end + // OR + + // JSON: + { + "Name":"Harry Pottery", + "Page": 256, + "Description": "A book written by J.K.Rowling." + "BookID" : 100010 + } + + // Model: + @interface Book : NSObject + @property NSString *name; + @property NSInteger page; + @property NSString *desc; + @property NSString *bookID; + @end + @implementation Book + + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + if ([propertyName isEqualToString:@"desc"]) { + return @"Description"; + } + // first letter uppercase + return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + } + @end + You can map a json key (key path) or an array of json key (key path) to one or multiple property name. If there's no mapper for a property, it will use the property's name as default. ###Nested model @@ -168,7 +195,7 @@ You can map a json key (key path) or an array of json key (key path) to one or m @end @implementation Author @end - + @interface Book : NSObject @property NSString *name; @property NSUInteger pages; @@ -176,8 +203,8 @@ You can map a json key (key path) or an array of json key (key path) to one or m @end @implementation Book @end - - + + ### Container property @@ -208,7 +235,7 @@ You can map a json key (key path) or an array of json key (key path) to one or m @property NSString *name; @property NSUInteger age; @end - + @implementation Attributes + (NSArray *)modelPropertyBlacklist { return @[@"test1", @"test2"]; @@ -219,13 +246,13 @@ You can map a json key (key path) or an array of json key (key path) to one or m @end ###Data validate and custom transform - + // JSON: { "name":"Harry", "timestamp" : 1445534567 } - + // Model: @interface User @property NSString *name; @@ -351,10 +378,10 @@ YYModel is provided under the MIT license. See LICENSE file for details. @implementation User @end - + // 将 JSON (NSData,NSString,NSDictionary) 转换为 Model: User *user = [User yy_modelWithJSON:json]; - + // 将 Model 转换为 JSON 对象: NSDictionary *json = [user yy_modelToJSONObject]; @@ -443,13 +470,43 @@ EEE MMM dd HH:mm:ss Z yyyy @"bookID" : @[@"id",@"ID",@"book_id"]}; } @end - + + // 或者 + + // JSON: + { + "Name":"Harry Pottery", + "Page": 256, + "Description": "A book written by J.K.Rowling." + "BookID" : 100010 + } + + // Model: + @interface Book : NSObject + @property NSString *name; + @property NSInteger page; + @property NSString *desc; + @property NSString *bookID; + @end + @implementation Book + //返回propertyName 对映射到 JSON 的 Key。 + + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + if ([propertyName isEqualToString:@"desc"]) { + return @"Description"; + } + // 首字母大字 + return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + } + @end + 你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。 在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。 - + 在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。 +modelCustomPropertyMapper和modelCustomKeyNameWithPropertyName只能使用其中一个,如果同时使用只有modelCustomPropertyMapper有效。 + ###Model 包含其他 Model // JSON @@ -469,7 +526,7 @@ EEE MMM dd HH:mm:ss Z yyyy @end @implementation Author @end - + @interface Book : NSObject @property NSString *name; @property NSUInteger pages; @@ -477,8 +534,8 @@ EEE MMM dd HH:mm:ss Z yyyy @end @implementation Book @end - - + + ###容器类属性 @@ -509,7 +566,7 @@ EEE MMM dd HH:mm:ss Z yyyy @property NSString *name; @property NSUInteger age; @end - + @implementation Attributes // 如果实现了该方法,则处理过程中会忽略该列表内的所有属性 + (NSArray *)modelPropertyBlacklist { @@ -522,13 +579,13 @@ EEE MMM dd HH:mm:ss Z yyyy @end ###数据校验与自定义转换 - + // JSON: { "name":"Harry", "timestamp" : 1445534567 } - + // Model: @interface User @property NSString *name; @@ -545,7 +602,7 @@ EEE MMM dd HH:mm:ss Z yyyy _createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue]; return YES; } - + // 当 Model 转为 JSON 完成后,该方法会被调用。 // 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。 // 你也可以在这里做一些自动转换不能完成的工作。 diff --git a/YYModel/NSObject+YYModel.h b/YYModel/NSObject+YYModel.h index 82032ec..b8a0a50 100644 --- a/YYModel/NSObject+YYModel.h +++ b/YYModel/NSObject+YYModel.h @@ -269,6 +269,8 @@ NS_ASSUME_NONNULL_BEGIN @discussion If the key in JSON/Dictionary does not match to the model's property name, implements this method and returns the additional mapper. + modelCustomPropertyMapper and modelCustomKeyNameWithPropertyName: Use only one of them. + Example: json: @@ -302,6 +304,50 @@ NS_ASSUME_NONNULL_BEGIN */ + (nullable NSDictionary *)modelCustomPropertyMapper; +/** + + Custom property name. + + @discussion If the key in JSON/Dictionary does not match to the model's property name + and has certain rules, implements this method and returns the corresponding + JSON/Dictionary key name. + + modelCustomPropertyMapper and modelCustomKeyNameWithPropertyName: Use only one of them. + + Example: + + json: + { + "Name":"Harry Pottery", + "Page": 256, + "Description": "A book written by J.K.Rowling." + "BookID" : 100010 + } + + model: + @interface YYBook : NSObject + @property NSString *name; + @property NSInteger page; + @property NSString *desc; + @property NSString *bookID; + @end + + @implementation YYBook + + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + if ([propertyName isEqualToString:@"desc"]) { + return @"Description"; + } + // first letter uppercase + return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + } + @end + + @param propertyName The model property name. + + @return A JSON/Dictionary key name. + */ ++ (nullable id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName; + /** The generic class mapper for container properties. diff --git a/YYModel/NSObject+YYModel.m b/YYModel/NSObject+YYModel.m index e92a6b1..857f7a6 100644 --- a/YYModel/NSObject+YYModel.m +++ b/YYModel/NSObject+YYModel.m @@ -546,62 +546,71 @@ - (instancetype)initWithClass:(Class)cls { NSMutableArray *keyPathPropertyMetas = [NSMutableArray new]; NSMutableArray *multiKeysPropertyMetas = [NSMutableArray new]; + NSDictionary *customMapper = nil; + if ([cls respondsToSelector:@selector(modelCustomPropertyMapper)]) { - NSDictionary *customMapper = [(id )cls modelCustomPropertyMapper]; - [customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) { - _YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName]; - if (!propertyMeta) return; - [allPropertyMetas removeObjectForKey:propertyName]; + customMapper = [(id )cls modelCustomPropertyMapper]; + } else if ([cls respondsToSelector:@selector(modelCustomKeyNameWithPropertyName:)]) { + NSMutableDictionary *tempCustomMapper = [NSMutableDictionary new]; + [allPropertyMetas enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, id _Nonnull obj, BOOL * _Nonnull stop) { + id mappedToKey = [(id )cls modelCustomKeyNameWithPropertyName:propertyName]; + if (mappedToKey) tempCustomMapper[propertyName] = mappedToKey; + }]; + if (tempCustomMapper.count) customMapper = tempCustomMapper; + } + [customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) { + _YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName]; + if (!propertyMeta) return; + [allPropertyMetas removeObjectForKey:propertyName]; + + if ([mappedToKey isKindOfClass:[NSString class]]) { + if (mappedToKey.length == 0) return; - if ([mappedToKey isKindOfClass:[NSString class]]) { - if (mappedToKey.length == 0) return; - - propertyMeta->_mappedToKey = mappedToKey; - NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."]; - for (NSString *onePath in keyPath) { - if (onePath.length == 0) { - NSMutableArray *tmp = keyPath.mutableCopy; - [tmp removeObject:@""]; - keyPath = tmp; - break; - } + propertyMeta->_mappedToKey = mappedToKey; + NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."]; + for (NSString *onePath in keyPath) { + if (onePath.length == 0) { + NSMutableArray *tmp = keyPath.mutableCopy; + [tmp removeObject:@""]; + keyPath = tmp; + break; } + } + if (keyPath.count > 1) { + propertyMeta->_mappedToKeyPath = keyPath; + [keyPathPropertyMetas addObject:propertyMeta]; + } + propertyMeta->_next = mapper[mappedToKey] ?: nil; + mapper[mappedToKey] = propertyMeta; + + } else if ([mappedToKey isKindOfClass:[NSArray class]]) { + + NSMutableArray *mappedToKeyArray = [NSMutableArray new]; + for (NSString *oneKey in ((NSArray *)mappedToKey)) { + if (![oneKey isKindOfClass:[NSString class]]) continue; + if (oneKey.length == 0) continue; + + NSArray *keyPath = [oneKey componentsSeparatedByString:@"."]; if (keyPath.count > 1) { - propertyMeta->_mappedToKeyPath = keyPath; - [keyPathPropertyMetas addObject:propertyMeta]; + [mappedToKeyArray addObject:keyPath]; + } else { + [mappedToKeyArray addObject:oneKey]; } - propertyMeta->_next = mapper[mappedToKey] ?: nil; - mapper[mappedToKey] = propertyMeta; - } else if ([mappedToKey isKindOfClass:[NSArray class]]) { - - NSMutableArray *mappedToKeyArray = [NSMutableArray new]; - for (NSString *oneKey in ((NSArray *)mappedToKey)) { - if (![oneKey isKindOfClass:[NSString class]]) continue; - if (oneKey.length == 0) continue; - - NSArray *keyPath = [oneKey componentsSeparatedByString:@"."]; - if (keyPath.count > 1) { - [mappedToKeyArray addObject:keyPath]; - } else { - [mappedToKeyArray addObject:oneKey]; - } - - if (!propertyMeta->_mappedToKey) { - propertyMeta->_mappedToKey = oneKey; - propertyMeta->_mappedToKeyPath = keyPath.count > 1 ? keyPath : nil; - } + if (!propertyMeta->_mappedToKey) { + propertyMeta->_mappedToKey = oneKey; + propertyMeta->_mappedToKeyPath = keyPath.count > 1 ? keyPath : nil; } - if (!propertyMeta->_mappedToKey) return; - - propertyMeta->_mappedToKeyArray = mappedToKeyArray; - [multiKeysPropertyMetas addObject:propertyMeta]; - - propertyMeta->_next = mapper[mappedToKey] ?: nil; - mapper[mappedToKey] = propertyMeta; } - }]; - } + if (!propertyMeta->_mappedToKey) return; + + propertyMeta->_mappedToKeyArray = mappedToKeyArray; + [multiKeysPropertyMetas addObject:propertyMeta]; + + propertyMeta->_next = mapper[mappedToKey] ?: nil; + mapper[mappedToKey] = propertyMeta; + } + }]; [allPropertyMetas enumerateKeysAndObjectsUsingBlock:^(NSString *name, _YYModelPropertyMeta *propertyMeta, BOOL *stop) { propertyMeta->_mappedToKey = name; diff --git a/YYModelTests/YYTestModelMapper.m b/YYModelTests/YYTestModelMapper.m index 4b52c8d..1a03cc6 100644 --- a/YYModelTests/YYTestModelMapper.m +++ b/YYModelTests/YYTestModelMapper.m @@ -32,6 +32,12 @@ @interface YYTestPropertyMapperModelCustom : NSObject @end @implementation YYTestPropertyMapperModelCustom +@end + +@interface YYTestPropertyMapperModelCustom1 : YYTestPropertyMapperModelCustom +@end + +@implementation YYTestPropertyMapperModelCustom1 + (NSDictionary *)modelCustomPropertyMapper { return @{ @"name" : @"n", @"count" : @"ext.c", @@ -43,6 +49,16 @@ + (NSDictionary *)modelCustomPropertyMapper { } @end +@interface YYTestPropertyMapperModelCustom2 : YYTestPropertyMapperModelCustom +@end + +@implementation YYTestPropertyMapperModelCustom2 ++ (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + NSDictionary *mapper = [YYTestPropertyMapperModelCustom1 modelCustomPropertyMapper]; + return mapper[propertyName]; +} +@end + @interface YYTestPropertyMapperModelWarn : NSObject { NSString *_description; } @@ -131,30 +147,30 @@ - (void)testAuto { XCTAssertTrue([model.count isEqual:@12]); } -- (void)testCustom { +- (void)_testCustomWithModel:(nonnull YYTestPropertyMapperModelCustom *)model { NSString *json; NSDictionary *jsonObject; - YYTestPropertyMapperModelCustom *model; + Class modelClass = [model class]; json = @"{\"n\":\"Apple\",\"ext\":{\"c\":12}}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.name isEqualToString:@"Apple"]); XCTAssertTrue([model.count isEqual:@12]); json = @"{\"n\":\"Apple\",\"count\":12}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue(model.count == nil); json = @"{\"n\":\"Apple\",\"ext\":12}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue(model.count == nil); json = @"{\"n\":\"Apple\",\"ext\":@{}}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue(model.count == nil); json = @"{\"ext\":{\"d\":\"Apple\"}}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.desc1 isEqualToString:@"Apple"]); XCTAssertTrue([model.desc2 isEqualToString:@"Apple"]); @@ -162,27 +178,27 @@ - (void)testCustom { XCTAssertTrue([((NSDictionary *)jsonObject[@"ext"])[@"d"] isEqualToString:@"Apple"]); json = @"{\"ext\":{\"d\":{ \"e\" : \"Apple\"}}}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.desc3 isEqualToString:@"Apple"]); json = @"{\".ext\":\"Apple\"}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.desc4 isEqualToString:@"Apple"]); json = @"{\".ext\":\"Apple\", \"name\":\"Apple\", \"count\":\"10\", \"desc1\":\"Apple\", \"desc2\":\"Apple\", \"desc3\":\"Apple\", \"desc4\":\"Apple\", \"modelID\":\"Apple\"}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.desc4 isEqualToString:@"Apple"]); json = @"{\"id\":\"abcd\"}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.modelID isEqualToString:@"abcd"]); json = @"{\"ext\":{\"id\":\"abcd\"}}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.modelID isEqualToString:@"abcd"]); json = @"{\"id\":\"abcd\",\"ID\":\"ABCD\",\"Id\":\"Abcd\"}"; - model = [YYTestPropertyMapperModelCustom yy_modelWithJSON:json]; + model = [modelClass yy_modelWithJSON:json]; XCTAssertTrue([model.modelID isEqualToString:@"ABCD"]); jsonObject = [model yy_modelToJSONObject]; @@ -190,6 +206,16 @@ - (void)testCustom { XCTAssertTrue([jsonObject[@"ID"] isEqualToString:@"ABCD"]); } +- (void)testCustom1 { + YYTestPropertyMapperModelCustom1 *model = [YYTestPropertyMapperModelCustom1 new]; + [self _testCustomWithModel:model]; +} + +- (void)testCustom2 { + YYTestPropertyMapperModelCustom2 *model = [YYTestPropertyMapperModelCustom2 new]; + [self _testCustomWithModel:model]; +} + - (void)testWarn { NSString *json = @"{\"description\":\"Apple\",\"id\":12345}"; YYTestPropertyMapperModelWarn *model = [YYTestPropertyMapperModelWarn yy_modelWithJSON:json]; From d887329e77fff13e3de3957c6bf39b2027f03a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=AF=E7=A3=8A?= Date: Fri, 24 Jun 2016 23:24:55 +0800 Subject: [PATCH 2/3] Update README.md --- README.md | 106 +++++++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 9be3af2..e03c914 100755 --- a/README.md +++ b/README.md @@ -147,32 +147,32 @@ EEE MMM dd HH:mm:ss Z yyyy } @end - // OR - - // JSON: - { - "Name":"Harry Pottery", - "Page": 256, - "Description": "A book written by J.K.Rowling." - "BookID" : 100010 - } - - // Model: - @interface Book : NSObject - @property NSString *name; - @property NSInteger page; - @property NSString *desc; - @property NSString *bookID; - @end - @implementation Book - + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { - if ([propertyName isEqualToString:@"desc"]) { - return @"Description"; - } - // first letter uppercase - return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; - } - @end + // OR + + // JSON: + { + "Name":"Harry Pottery", + "Page": 256, + "Description": "A book written by J.K.Rowling." + "BookID" : 100010 + } + + // Model: + @interface Book : NSObject + @property NSString *name; + @property NSInteger page; + @property NSString *desc; + @property NSString *bookID; + @end + @implementation Book + + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + if ([propertyName isEqualToString:@"desc"]) { + return @"Description"; + } + // first letter uppercase + return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + } + @end You can map a json key (key path) or an array of json key (key path) to one or multiple property name. If there's no mapper for a property, it will use the property's name as default. @@ -471,33 +471,33 @@ EEE MMM dd HH:mm:ss Z yyyy } @end - // 或者 - - // JSON: - { - "Name":"Harry Pottery", - "Page": 256, - "Description": "A book written by J.K.Rowling." - "BookID" : 100010 - } - - // Model: - @interface Book : NSObject - @property NSString *name; - @property NSInteger page; - @property NSString *desc; - @property NSString *bookID; - @end - @implementation Book - //返回propertyName 对映射到 JSON 的 Key。 - + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { - if ([propertyName isEqualToString:@"desc"]) { - return @"Description"; - } - // 首字母大字 - return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; - } - @end + // 或者 + + // JSON: + { + "Name":"Harry Pottery", + "Page": 256, + "Description": "A book written by J.K.Rowling." + "BookID" : 100010 + } + + // Model: + @interface Book : NSObject + @property NSString *name; + @property NSInteger page; + @property NSString *desc; + @property NSString *bookID; + @end + @implementation Book + //返回propertyName 对映射到 JSON 的 Key。 + + (id)modelCustomKeyNameWithPropertyName:(NSString *)propertyName { + if ([propertyName isEqualToString:@"desc"]) { + return @"Description"; + } + // 首字母大字 + return [NSString stringWithFormat:@"%@%@", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + } + @end 你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。 From 28f1a6307a9daea779382c34cb4668a221d101e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=AF=E7=A3=8A?= Date: Fri, 24 Jun 2016 23:44:47 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=9D=E6=8C=81=E5=8E=9F=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=B1=82=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YYModel/NSObject+YYModel.m | 95 +++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/YYModel/NSObject+YYModel.m b/YYModel/NSObject+YYModel.m index 857f7a6..14a8285 100644 --- a/YYModel/NSObject+YYModel.m +++ b/YYModel/NSObject+YYModel.m @@ -547,7 +547,6 @@ - (instancetype)initWithClass:(Class)cls { NSMutableArray *multiKeysPropertyMetas = [NSMutableArray new]; NSDictionary *customMapper = nil; - if ([cls respondsToSelector:@selector(modelCustomPropertyMapper)]) { customMapper = [(id )cls modelCustomPropertyMapper]; } else if ([cls respondsToSelector:@selector(modelCustomKeyNameWithPropertyName:)]) { @@ -558,59 +557,61 @@ - (instancetype)initWithClass:(Class)cls { }]; if (tempCustomMapper.count) customMapper = tempCustomMapper; } - [customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) { - _YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName]; - if (!propertyMeta) return; - [allPropertyMetas removeObjectForKey:propertyName]; - - if ([mappedToKey isKindOfClass:[NSString class]]) { - if (mappedToKey.length == 0) return; - - propertyMeta->_mappedToKey = mappedToKey; - NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."]; - for (NSString *onePath in keyPath) { - if (onePath.length == 0) { - NSMutableArray *tmp = keyPath.mutableCopy; - [tmp removeObject:@""]; - keyPath = tmp; - break; - } - } - if (keyPath.count > 1) { - propertyMeta->_mappedToKeyPath = keyPath; - [keyPathPropertyMetas addObject:propertyMeta]; - } - propertyMeta->_next = mapper[mappedToKey] ?: nil; - mapper[mappedToKey] = propertyMeta; + if (customMapper) { + [customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) { + _YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName]; + if (!propertyMeta) return; + [allPropertyMetas removeObjectForKey:propertyName]; - } else if ([mappedToKey isKindOfClass:[NSArray class]]) { - - NSMutableArray *mappedToKeyArray = [NSMutableArray new]; - for (NSString *oneKey in ((NSArray *)mappedToKey)) { - if (![oneKey isKindOfClass:[NSString class]]) continue; - if (oneKey.length == 0) continue; + if ([mappedToKey isKindOfClass:[NSString class]]) { + if (mappedToKey.length == 0) return; - NSArray *keyPath = [oneKey componentsSeparatedByString:@"."]; + propertyMeta->_mappedToKey = mappedToKey; + NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."]; + for (NSString *onePath in keyPath) { + if (onePath.length == 0) { + NSMutableArray *tmp = keyPath.mutableCopy; + [tmp removeObject:@""]; + keyPath = tmp; + break; + } + } if (keyPath.count > 1) { - [mappedToKeyArray addObject:keyPath]; - } else { - [mappedToKeyArray addObject:oneKey]; + propertyMeta->_mappedToKeyPath = keyPath; + [keyPathPropertyMetas addObject:propertyMeta]; } + propertyMeta->_next = mapper[mappedToKey] ?: nil; + mapper[mappedToKey] = propertyMeta; + + } else if ([mappedToKey isKindOfClass:[NSArray class]]) { - if (!propertyMeta->_mappedToKey) { - propertyMeta->_mappedToKey = oneKey; - propertyMeta->_mappedToKeyPath = keyPath.count > 1 ? keyPath : nil; + NSMutableArray *mappedToKeyArray = [NSMutableArray new]; + for (NSString *oneKey in ((NSArray *)mappedToKey)) { + if (![oneKey isKindOfClass:[NSString class]]) continue; + if (oneKey.length == 0) continue; + + NSArray *keyPath = [oneKey componentsSeparatedByString:@"."]; + if (keyPath.count > 1) { + [mappedToKeyArray addObject:keyPath]; + } else { + [mappedToKeyArray addObject:oneKey]; + } + + if (!propertyMeta->_mappedToKey) { + propertyMeta->_mappedToKey = oneKey; + propertyMeta->_mappedToKeyPath = keyPath.count > 1 ? keyPath : nil; + } } + if (!propertyMeta->_mappedToKey) return; + + propertyMeta->_mappedToKeyArray = mappedToKeyArray; + [multiKeysPropertyMetas addObject:propertyMeta]; + + propertyMeta->_next = mapper[mappedToKey] ?: nil; + mapper[mappedToKey] = propertyMeta; } - if (!propertyMeta->_mappedToKey) return; - - propertyMeta->_mappedToKeyArray = mappedToKeyArray; - [multiKeysPropertyMetas addObject:propertyMeta]; - - propertyMeta->_next = mapper[mappedToKey] ?: nil; - mapper[mappedToKey] = propertyMeta; - } - }]; + }]; + } [allPropertyMetas enumerateKeysAndObjectsUsingBlock:^(NSString *name, _YYModelPropertyMeta *propertyMeta, BOOL *stop) { propertyMeta->_mappedToKey = name;