具体思想:
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-