下面是一段json
{
"cover": [
{
"height": 464,
"mediaUrl": "T3siZTB7YT1RCvBVdK.jpg",
"width": 464
},
{
"height": 464,
"mediaUrl": "T3ohWTBj_T1RCvBVdK.jpg",
"width": 464
}
],
"title": "蒹葭苍苍,白露为霜",
"cretateTime":32938938394,
"user": {
"uid": 18222,
"username": "曹晓文"
}
}
JSON的解析过程这里分为三个步骤:
- 获取Model类和他父类的属性列表,还有属性的类型
- 将JSON转换为我们需要的数据类型,比如字符串、数值、数组,自定义对象,BOOL, URL, 日期
- 把转换好的数据赋值给对象的属性property
下面介绍下具体的实现过程
- 获取model类以及父类的属性列表和属性的类型
- 使用runtime提供的函数去遍历model类所有的属性
runtime是Objective C的运行时机制,提供了一系列函数,包括获取方法列表、属性列表、变量列表,修改方法、属性,增加方法,属性等等 - 下面通过class_copyPropertyList获取属性列表,从而获取属性名称
+ (void)enumeratePropertiesUsingBlock:(void (^)(objc_property_t property, BOOL *stop))block {
Class cls = self;
BOOL stop = NO;
while (!stop && ![cls isEqual:MTLModel.class]) {
unsigned count = 0;
objc_property_t *properties = class_copyPropertyList(cls, &count);
cls = cls.superclass;
if (properties == NULL) continue;
@onExit {
free(properties);
};
for (unsigned i = 0; i < count; i++) {
block(properties[i], &stop);
if (stop) break;
}
}
}
+ (NSDictionary *)mtl_identityPropertyMapWithModel:(Class)modelClass {
NSCParameterAssert([modelClass conformsToProtocol:@protocol(MTLModel)]);
NSArray *propertyKeys = [modelClass propertyKeys].allObjects;
return [NSDictionary dictionaryWithObjects:propertyKeys forKeys:propertyKeys];
}
- 通过property_getAttributes获取属性对应的类型
mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property) {
const char * const attrString = property_getAttributes(property);
/*attrString 输出之后: T@\"NSString\",C,N,V_name
T: T 后面是放的是该属性的数据类型
N: nonatomic
V: V 后面放的是该属性的变量名称(因为我们知道 @property 实际上只是为我们编写好了 getter 和 setter 方法,并创建一个以下划线开头的变量)
**/
...
mtl_propertyAttributes *attributes = calloc(1, sizeof(mtl_propertyAttributes) + typeLength + 1);
...
return attributes;
}
- 将JSON转换为我们需要的数据类型,比如字符串、数值、数组,自定义对象,BOOL, URL, 日期
转换器类 MTLValueTransformer, 如果json中的数据类型和我们实际需要的类型不一致的时候,我们也可以自定义一个转换器,转换为我们需要的类型,例如
//自定义的
+ (NSValueTransformer *)nameJSONTransformer
{
return [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) {
//将value转换为合适的类型
return [value stringValue];
} reverseBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) {
return @([value integerValue]);
}];
}
+ (NSValueTransformer *)itemsJSONTransformer
{
return [MTLJSONAdapter arrayTransformerWithModelClass:[DJRelatedGoodsModel class]];
}
//mantle里自带的Transformer
+ (NSValueTransformer *)NSURLJSONTransformer {
return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
}
+ (NSValueTransformer *)NSUUIDJSONTransformer {
return [NSValueTransformer valueTransformerForName:MTLUUIDValueTransformerName];
}
+ (NSValueTransformer<MTLTransformerErrorHandling> *)dictionaryTransformerWithModelClass:(Class)modelClass {
NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLModel)]);
NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]);
__block MTLJSONAdapter *adapter;
return [MTLValueTransformer
transformerUsingForwardBlock:^ id (id JSONDictionary, BOOL *success, NSError **error) {
if (JSONDictionary == nil) return nil;
...
id model = [adapter modelFromJSONDictionary:JSONDictionary error:error];
if (model == nil) {
*success = NO;
}
return model;
}
reverseBlock:^ NSDictionary * (id model, BOOL *success, NSError **error) {
if (model == nil) return nil;
...
NSDictionary *result = [adapter JSONDictionaryFromModel:model error:error];
if (result == nil) {
*success = NO;
}
return result;
}];
}
+ (NSValueTransformer<MTLTransformerErrorHandling> *)arrayTransformerWithModelClass:(Class)modelClass {
id<MTLTransformerErrorHandling> dictionaryTransformer = [self dictionaryTransformerWithModelClass:modelClass];
return [MTLValueTransformer
transformerUsingForwardBlock:^ id (NSArray *dictionaries, BOOL *success, NSError **error) {
if (dictionaries == nil) return nil;
...
NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count];
for (id JSONDictionary in dictionaries) {
...
id model = [dictionaryTransformer transformedValue:JSONDictionary success:success error:error];
...
[models addObject:model];
}
return models;
}
reverseBlock:^ id (NSArray *models, BOOL *success, NSError **error) {
...
NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count];
for (id model in models) {
...
NSDictionary *dict = [dictionaryTransformer reverseTransformedValue:model success:success error:error];
...
[dictionaries addObject:dict];
}
return dictionaries;
}];
}
- 把转换好的数据赋值给对象的属性property
- (instancetype)initWithDictionary:(NSDictionary *)dictionary error:(NSError **)error {
self = [self init];
if (self == nil) return nil;
for (NSString *key in dictionary) {
__autoreleasing id value = [dictionary objectForKey:key];
if ([value isEqual:NSNull.null]) value = nil;
BOOL success = MTLValidateAndSetValue(self, key, value, YES, error);
//[obj setValue:validatedValue forKey:key];
if (!success) return nil;
}
return self;
}
网友评论