json数据转化成模型对象

时间:2022-12-02 17:56:41

具体思想:

1.将模型对象的属性名和属性类型的创建规则  应与json数据的key-value一一对应。

2.在模型对象初始化之前,给模型对象的每一个属性名赋默认的值。比较 NSString类型默认赋值@"",NSNumber默认赋值

[NSNull null]

3.以json数据的key作为属性名,value作为值给模型数据一一赋值。

 

 

有三个重要的方法:

// 获取类的所有Property

1. objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)

// 获取一个Property的变量名

2. const char *property_getName(objc_property_t property)

// 获取一个Property的详细类型表达字符串

3. const char *property_getAttributes(objc_property_t property)

 

如下面方法可以读取模型(model)里的每一个属性,并且将属性名和类型转换成key-value的形式保存起来

static NSDictionary *primitivesNames = nil;
//获取一个类的属性名和类型
+(NSDictionary*)getClassPropertysAndType
{
    if(primitivesNames== nil){
        primitivesNames = @{@"f":@"float", @"i":@"int", @"d":@"double", @"l":@"long", @"c":@"BOOL", @"s":@"short", @"q":@"long",
                            //and some famos aliases of primitive types
                            // BOOL is now "B" on iOS __LP64 builds
                            @"I":@"NSInteger", @"Q":@"NSUInteger", @"B":@"BOOL",
                            
                            @"@?":@"Block"};
    }
    NSMutableDictionary *properts_info = [[NSMutableDictionary alloc] init];
    
    Class curClass = [self class];
    NSScanner *scanner = nil;
    NSString* propertyType = nil;
    
    while (curClass && curClass != [NSObject class]) {
        
        objc_property_t  *propItems;
        unsigned int     ncount = 0;
//        获取类的所有Property
        propItems = class_copyPropertyList(curClass, &ncount);
        
        for(int i = 0; i < ncount; i++){
            objc_property_t prop_item = propItems[i];
            // 获取一个Property的变量名
            const char *properName = property_getName(prop_item);
            // 获取一个Property的详细类型表达字符串
            const char *attribute = property_getAttributes(prop_item);
            
            NSString* propertyAttributes = @(attribute);
            
            // NSLog(@"---------->property attributes:%@",propertyAttributes);
            
            NSString  *proper_Name = @(properName);
            
            NSArray* attributeItems = [propertyAttributes componentsSeparatedByString:@","];
            //ignore read-only properties
            if([attributeItems containsObject:@"R"]){
                continue;//to next property
            }
            
            //check for 64b BOOLs
            if ([propertyAttributes hasPrefix:@"Tc,"]) {
                //mask BOOLs as structs so they can have custom convertors
                propertyType = @"BOOL";
            }
            
            scanner = [NSScanner scannerWithString:propertyAttributes];
            [scanner scanUpToString:@"T" intoString: nil];
            [scanner scanString:@"T" intoString:nil];
            
            //check if the property is an instance of a class
            if ([scanner scanString:@"@\"" intoString: &propertyType]) {
                
                [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"<"]
                                        intoString:&propertyType];
                
                //read through the property protocols
                while ([scanner scanString:@"<" intoString:NULL]) {
                    
                    [scanner scanUpToString:@">" intoString:&propertyType];
                    
                    [scanner scanString:@">" intoString:NULL];
                }
            }
            //check if the property is a structure
            else if ([scanner scanString:@"{" intoString: &propertyType]) {
                [scanner scanCharactersFromSet:[NSCharacterSet alphanumericCharacterSet]
                                    intoString:&propertyType];
                
            }
            else if([[attributeItems firstObject] isEqualToString:@"T@"]){
                propertyType = @"id";
            }
            else if([[attributeItems firstObject] isEqualToString:@"T@?"]){
                propertyType = @"Block";
            }
            //the property must be a primitive
            else {
                //the property contains a primitive data type
                [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@","]
                                        intoString:&propertyType];
                //get the full name of the primitive type
                propertyType = primitivesNames[propertyType];
            }
            
            if(propertyType){
                properts_info[proper_Name] = propertyType;
            }
            
        }
        free(propItems);
        
        curClass = [curClass superclass];
    }
    
    NSDictionary *prop_info = [properts_info copy];
    properts_info = nil;
    
    return prop_info;
}

 具体实现过程,可在github中下载源代码。下载路径:https://github.com/wydxy/json-