iOS JSON数据解析过程-Mantle

2018-09-06  本文已影响0人  淡燃

下面是一段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的解析过程这里分为三个步骤:

  1. 获取Model类和他父类的属性列表,还有属性的类型
  2. 将JSON转换为我们需要的数据类型,比如字符串、数值、数组,自定义对象,BOOL, URL, 日期
  3. 把转换好的数据赋值给对象的属性property

下面介绍下具体的实现过程

  1. 获取model类以及父类的属性列表和属性的类型
+ (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];
}
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;
}
  1. 将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;
        }];
}
  1. 把转换好的数据赋值给对象的属性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;
}
上一篇下一篇

猜你喜欢

热点阅读