MJExtention 字典转模型详解使用注意以及利用runtime字典转模型的使用注意

来源:互联网 发布:脍炙人口的网络歌曲 编辑:程序博客网 时间:2024/06/06 09:19

字典转模型的原理就是:根据属性名去字典中寻中对应的key,找到对应的value,然后把value的值赋给属性;


以往我们都是利用KVC进行字典转模型,但是它还是有一定的局限性,例如:模型属性和键值对对应不上会crash(虽然可以重写setValue:forUndefinedKey:方法防止报错),模型属性是一个对象或者数组时不好处理等问题,所以无论是效率还是功能上,利用runtime进行字典转模型都是比较好的选择。

字典转模型我们需要考虑三种特殊情况:
1.当字典的key和模型的属性匹配不上
2.模型中嵌套模型(模型属性是另外一个模型对象)
3.数组中装着模型(模型的属性是一个数组,数组中是一个个模型对象)

  1. 根据上面的三种特殊情况,我们一个个处理,先是字典的key和模型的属性不对应的情况。
    不对应有两种,一种是字典的键值大于模型属性数量,这时候我们不需要任何处理,因为runtime是先遍历模型所有属性,再去字典中根据属性名找对应值进行赋值,多余的键值对也当然不会去看了;另外一种是模型属性数量大于字典的键值对,这时候由于属性没有对应值会被赋值为nil,就会导致crash,我们只需加一个判断即可,

2.

第二种情况是模型的属性是另外一个模型对象。


JSON数据

这时候我们就需要利用runtime的ivar_getTypeEncoding 方法获取模型对象类型,对该模型对象类型再进行字典转模型,也就是进行递归,需要注意的是我们要排除系统的对象类型,例如NSString,下面的方法中我添加了一个类方法方便递归。


打印可以看到各属性类型

举例:
- (void)setDict:(NSDictionary *)dict {    Class c = self.class;    while (c &&c != [NSObject class]) {        unsigned int outCount = 0;        Ivar *ivars = class_copyIvarList(c, &outCount);        for (int i = 0; i < outCount; i++) {            Ivar ivar = ivars[i];            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];            // 成员变量名转为属性名(去掉下划线 _ )            key = [key substringFromIndex:1];            // 取出字典的值            id value = dict[key];            // 如果模型属性数量大于字典键值对数理,模型属性会被赋值为nil而报错            if (value == nil) continue;            // 获得成员变量的类型            NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];            // 如果属性是对象类型            NSRange range = [type rangeOfString:@"@"];            if (range.location != NSNotFound) {                // 那么截取对象的名字(比如@"Dog",截取为Dog)                type = [type substringWithRange:NSMakeRange(2, type.length - 3)];                // 排除系统的对象类型                if (![type hasPrefix:@"NS"]) {                    // 将对象名转换为对象的类型,将新的对象字典转模型(递归)                    Class class = NSClassFromString(type);                    value = [class objectWithDict:value];                }            }            // 将字典中的值设置到模型上            [self setValue:value forKeyPath:key];        }        free(ivars);        c = [c superclass];    }}+ (instancetype )objectWithDict:(NSDictionary *)dict {    NSObject *obj = [[self alloc]init];    [obj setDict:dict];    return obj;}

第三种情况是模型的属性是一个数组,数组中是一个个模型对象,例如下面的数据我就可以通过books[0].name获取到C语言程序设计


JSON数据

我们既然能获取到属性类型,那就可以拦截到模型的那个数组属性,进而对数组中每个模型遍历并字典转模型,但是我们不知道数组中的模型都是什么类型,我们可以声明一个方法,该方法目的不是让其调用,而是让其实现并返回模型的类型。
这块语言可能解释不太清楚,可以参考我的demo,直接运行即可。

NSObject+JSONExtension.h

// 返回数组中都是什么类型的模型对象- (NSString *)arrayObjectClass ;

NSObject+JSONExtension.m

#import "NSObject+JSONExtension.h"#import <objc/runtime.h>@implementation NSObject (JSONExtension)- (void)setDict:(NSDictionary *)dict {    Class c = self.class;    while (c &&c != [NSObject class]) {        unsigned int outCount = 0;        Ivar *ivars = class_copyIvarList(c, &outCount);        for (int i = 0; i < outCount; i++) {            Ivar ivar = ivars[i];            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];            // 成员变量名转为属性名(去掉下划线 _ )            key = [key substringFromIndex:1];            // 取出字典的值            id value = dict[key];            // 如果模型属性数量大于字典键值对数理,模型属性会被赋值为nil而报错            if (value == nil) continue;            // 获得成员变量的类型            NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];            // 如果属性是对象类型            NSRange range = [type rangeOfString:@"@"];            if (range.location != NSNotFound) {                // 那么截取对象的名字(比如@"Dog",截取为Dog)                type = [type substringWithRange:NSMakeRange(2, type.length - 3)];                // 排除系统的对象类型                if (![type hasPrefix:@"NS"]) {                    // 将对象名转换为对象的类型,将新的对象字典转模型(递归)                    Class class = NSClassFromString(type);                    value = [class objectWithDict:value];                }else if ([type isEqualToString:@"NSArray"]) {                    // 如果是数组类型,将数组中的每个模型进行字典转模型,先创建一个临时数组存放模型                    NSArray *array = (NSArray *)value;                    NSMutableArray *mArray = [NSMutableArray array];                    // 获取到每个模型的类型                    id class ;                    if ([self respondsToSelector:@selector(arrayObjectClass)]) {                        NSString *classStr = [self arrayObjectClass];                        class = NSClassFromString(classStr);                    }                    // 将数组中的所有模型进行字典转模型                    for (int i = 0; i < array.count; i++) {                        [mArray addObject:[class objectWithDict:value[i]]];                    }                    value = mArray;                }            }            // 将字典中的值设置到模型上            [self setValue:value forKeyPath:key];        }        free(ivars);        c = [c superclass];    }}+ (instancetype )objectWithDict:(NSDictionary *)dict {    NSObject *obj = [[self alloc]init];    [obj setDict:dict];    return obj;}@end
 
========================





启动部分没有写在ViewController和AppDelegate里面,而是写在了main文件里面,并且用的是C函数。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. execute(keyValues2object, @"简单的字典 -> 模型");  
  2. execute(keyValues2object1@"JSON字符串 -> 模型");  
  3. execute(keyValues2object2@"复杂的字典 -> 模型 (模型里面包含了模型)");  
  4. execute(keyValues2object3@"复杂的字典 -> 模型 (模型的数组属性里面又装着模型)");  
  5. execute(keyValues2object4@"简单的字典 -> 模型(key替换,比如ID和id,支持多级映射)");  
  6. execute(keyValuesArray2objectArray, @"字典数组 -> 模型数组");  
  7. execute(object2keyValues, @"模型转字典");  
  8. execute(objectArray2keyValuesArray, @"模型数组 -> 字典数组");  
  9. execute(coreData, @"CoreData示例");  
  10. execute(coding, @"NSCoding示例");  
  11. execute(replacedKeyFromPropertyName121@"统一转换属性名(比如驼峰转下划线)");  
  12. execute(newValueFromOldValue, @"过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@"")");  
  13. execute(logAllProperties, @"使用MJExtensionLog打印模型的所有属性");  

想运行哪个就注释掉其他的就好了。


====================MJExtension.h=======================

MJExtension.h中引用以下头文件,方便以后一次性导入,

#import "NSObject+MJCoding.h"

#import "NSObject+MJProperty.h"

#import "NSObject+MJClass.h"

#import "NSObject+MJKeyValue.h"

#import "NSString+MJExtension.h"

#import "MJExtensionConst.h"

========***********MJExtensionConst.h******************=============MJExtensionConst.h中定义了一群常量成员变量类型(属性类型)

NSString *const MJPropertyTypeInt =@"i";

NSString *const MJPropertyTypeShort =@"s";

NSString *const MJPropertyTypeFloat =@"f";

NSString *const MJPropertyTypeDouble =@"d";

NSString *const MJPropertyTypeLong =@"l";

NSString *const MJPropertyTypeLongLong =@"q";

NSString *const MJPropertyTypeChar =@"c";

NSString *const MJPropertyTypeBOOL1 =@"c";

NSString *const MJPropertyTypeBOOL2 =@"b";

NSString *const MJPropertyTypePointer =@"*";


NSString *const MJPropertyTypeIvar =@"^{objc_ivar=}";

NSString *const MJPropertyTypeMethod =@"^{objc_method=}";

NSString *const MJPropertyTypeBlock =@"@?";

NSString *const MJPropertyTypeClass =@"#";

NSString *const MJPropertyTypeSEL =@":";

NSString *const MJPropertyTypeId =@"@";


========*************MJFoundation*******=============

这个类中是用来判断类是不自己定义的foundation中的类:

+ (NSSet *)foundationClasses

{


    if (foundationClasses_ ==nil) {

        // 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断

        foundationClasses_ = [NSSetsetWithObjects:

                              [NSURLclass],

                              [NSDateclass],

                              [NSValueclass],

                              [NSDataclass],

                              [NSErrorclass],

                              [NSArrayclass],

                              [NSDictionaryclass],

                              [NSStringclass],

                              [NSAttributedStringclass],nil];

    }

    returnfoundationClasses_;

    

    

}


//判断类型是否来自自己定义的foundation框架

+ (BOOL)isClassFromFoundation:(Class)c

{

    if (c == [NSObjectclass] || c == [NSManagedObjectclass])returnYES;

    

    __blockBOOL result =NO;

    [[selffoundationClasses]enumerateObjectsUsingBlock:^(Class foundationClass,BOOL *stop) {

        if ([cisSubclassOfClass:foundationClass]) {

            result = YES;

            *stop = YES;

        }

    }];

    return result;

}


========*************

"MJProperty.h"

*******=============

包装一个成员:

@interface MJProperty : NSObject

/** 成员属性 */

@property (nonatomic,assign)objc_property_t property;

/** 成员属性的名字 */

@property (nonatomic,readonly)NSString *name;


/** 成员属性的类型 */

@property (nonatomic,readonly)MJPropertyType *type;

/** 成员属性来源于哪个类(可能是父类) */

@property (nonatomic,assign) Class srcClass;


/**** 同一个成员属性 -父类和子类的行为可能不一致(originKeypropertyKeysobjectClassInArray ****/

/** 设置最原始的key */

- (void)setOriginKey:(id)originKey forClass:(Class)c;

/** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */

- (NSArray *)propertyKeysForClass:(Class)c;


/** 模型数组中的模型类型 */

- (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c;

- (Class)objectClassInArrayForClass:(Class)c;

/**** 同一个成员变量 -父类和子类的行为可能不一致(keykeysobjectClassInArray ****/


/**

 * 设置object的成员变量值

 */

- (void)setValue:(id)value forObject:(id)object;

/**

 * 得到object的成员属性值

 */

- (id)valueForObject:(id)object;


/**

 *  初始化

 */

+ (instancetype)cachedPropertyWithProperty:(objc_property_t)property;


@end



========*************

"MJPropertyKey.h"属性的键

*******=============

typedef enum {

    MJPropertyKeyTypeDictionary = 0,//字典的key

    MJPropertyKeyTypeArray // 数组的key

} MJPropertyKeyType;


/**

 *  属性的key

 */

@interface MJPropertyKey : NSObject

/** key的名字 */

@property (copy,  nonatomic)NSString *name;

/** key的种类,可能是@"10",可能是@"age" */

@property (assign,nonatomic)MJPropertyKeyType type;


/**

 *  根据当前的key,也就是name,从object(字典或者数组)中取值

 */

- (id)valueInObject:(id)object;


@end


========*************

"MJPropertyType.h"属性的类型

*******=============

/**

 *  包装一种类型

 */

@interface MJPropertyType : NSObject

/** 类型标识符 */

@property (nonatomic,copy)NSString *code;


/** 是否为id类型 */

@property (nonatomic,readonly,getter=isIdType)BOOL idType;


/** 是否为基本数字类型:intfloat */

@property (nonatomic,readonly,getter=isNumberType)BOOL numberType;


/** 是否为BOOL类型 */

@property (nonatomic,readonly,getter=isBoolType)BOOL boolType;


/** 对象类型(如果是基本数据类型,此值为nil */

@property (nonatomic,readonly) Class typeClass;


/** 类型是否来自于Foundation框架,比如NSStringNSArray */

@property (nonatomic,readonly,getter = isFromFoundation)BOOL fromFoundation;

/** 类型是否不支持KVC */

@property (nonatomic,readonly,getter = isKVCDisabled)BOOL KVCDisabled;


/**

 *  获得缓存的类型对象

 */

+ (instancetype)cachedTypeWithCode:(NSString *)code;

@end


============*****

 "NSObject+MJClass.h"

********============

/**

 *  遍历所有类的block(父类)

 */

typedef void (^MJClassesEnumeration)(Class c,BOOL *stop);


/** 这个数组中的属性名才会进行字典和模型的转换 */

typedef NSArray * (^MJAllowedPropertyNames)();

/** 这个数组中的属性名才会进行归档 */

typedef NSArray * (^MJAllowedCodingPropertyNames)();


/** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */

typedef NSArray * (^MJIgnoredPropertyNames)();

/** 这个数组中的属性名将会被忽略:不进行归档 */

typedef NSArray * (^MJIgnoredCodingPropertyNames)();


/**

 * 类相关的扩展

 */

@interface NSObject (MJClass)

/**

 *  遍历所有的类

 */

+ (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration;

+ (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration;


#pragma mark - 属性白名单配置

/**

 *  这个数组中的属性名才会进行字典和模型的转换

 *

 *  @param allowedPropertyNames          这个数组中的属性名才会进行字典和模型的转换

 */

+ (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;


/**

 *  这个数组中的属性名才会进行字典和模型的转换

 */

+ (NSMutableArray *)mj_totalAllowedPropertyNames;


#pragma mark - 属性黑名单配置

/**

 *  这个数组中的属性名将会被忽略:不进行字典和模型的转换

 *

 *  @param ignoredPropertyNames          这个数组中的属性名将会被忽略:不进行字典和模型的转换

 */

+ (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames;


/**

 *  这个数组中的属性名将会被忽略:不进行字典和模型的转换

 */

+ (NSMutableArray *)mj_totalIgnoredPropertyNames;


#pragma mark - 归档属性白名单配置

/**

 *  这个数组中的属性名才会进行归档

 *

 *  @param allowedCodingPropertyNames          这个数组中的属性名才会进行归档

 */

+ (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames;


/**

 *  这个数组中的属性名才会进行字典和模型的转换

 */

+ (NSMutableArray *)mj_totalAllowedCodingPropertyNames;


#pragma mark - 归档属性黑名单配置

/**

 *  这个数组中的属性名将会被忽略:不进行归档

 *

 *  @param ignoredCodingPropertyNames          这个数组中的属性名将会被忽略:不进行归档

 */

+ (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames;


/**

 *  这个数组中的属性名将会被忽略:不进行归档

 */

+ (NSMutableArray *)mj_totalIgnoredCodingPropertyNames;


#pragma mark - 内部使用

+ (void)mj_setupBlockReturnValue:(id (^)())block key:(constchar *)key;

@end





=============*********"NSObject+MJCoding.h"*****===============

/**

 *  Codeing协议

 */

@protocol MJCoding <NSObject>

@optional

/**

 *  这个数组中的属性名才会进行归档

 */

+ (NSArray *)mj_allowedCodingPropertyNames;

/**

 *  这个数组中的属性名将会被忽略:不进行归档

 */

+ (NSArray *)mj_ignoredCodingPropertyNames;

@end


@interface NSObject (MJCoding) <MJCoding>

/**

 *  解码(从文件中解析对象)

 */

- (void)mj_decode:(NSCoder *)decoder;

/**

 *  编码(将对象写入文件中)

 */

- (void)mj_encode:(NSCoder *)encoder;

@end



===============***********

"NSObject+MJKeyValue.h"

*******==========

/**

 *  KeyValue协议

 */

@protocol MJKeyValue <NSObject>

@optional

/**

 *  只有这个数组中的属性名才允许进行字典和模型的转换

 */

+ (NSArray *)mj_allowedPropertyNames;


/**

 *  这个数组中的属性名将会被忽略:不进行字典和模型的转换

 */

+ (NSArray *)mj_ignoredPropertyNames;


/**

 *  将属性名换为其他key去字典中取值

 *

 *  @return 字典中的key是属性名,value是从字典中取值用的key

 */

+ (NSDictionary *)mj_replacedKeyFromPropertyName;


/**

 *  将属性名换为其他key去字典中取值

 *

 *  @return 从字典中取值用的key

 */

+ (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName;


/**

 *  数组中需要转换的模型类

 *

 *  @return 字典中的key是数组属性名,value是数组中存放模型的ClassClass类型或者NSString类型)

 */

+ (NSDictionary *)mj_objectClassInArray;


/**

 *  旧值换新值,用于过滤字典中的值

 *

 *  @param oldValue 旧值

 *

 *  @return 新值

 */

- (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property;


/**

 *  当字典转模型完毕时调用

 */

- (void)mj_keyValuesDidFinishConvertingToObject;


/**

 *  当模型转字典完毕时调用

 */

- (void)mj_objectDidFinishConvertingToKeyValues;

@end


@interface NSObject (MJKeyValue) <MJKeyValue>

#pragma mark - 类方法

/**

 * 字典转模型过程中遇到的错误

 */

+ (NSError *)mj_error;


/**

 *  模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来)

 */

+ (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference;


#pragma mark - 对象方法

/**

 *  将字典的键值对转成模型属性

 *  @param keyValues 字典(可以是NSDictionaryNSDataNSString)

 */

- (instancetype)mj_setKeyValues:(id)keyValues;


/**

 *  将字典的键值对转成模型属性

 *  @param keyValues 字典(可以是NSDictionaryNSDataNSString)

 *  @param context   CoreData上下文

 */

- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;


/**

 *  将模型转成字典

 *  @return 字典

 */

- (NSMutableDictionary *)mj_keyValues;

- (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys;

- (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys;


/**

 *  通过模型数组来创建一个字典数组

 *  @param objectArray 模型数组

 *  @return 字典数组

 */

+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray;

+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys;

+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys;


#pragma mark - 字典转模型

/**

 *  通过字典来创建一个模型

 *  @param keyValues 字典(可以是NSDictionaryNSDataNSString)

 *  @return 新建的对象

 */

+ (instancetype)mj_objectWithKeyValues:(id)keyValues;


/**

 *  通过字典来创建一个CoreData模型

 *  @param keyValues 字典(可以是NSDictionaryNSDataNSString)

 *  @param context   CoreData上下文

 *  @return 新建的对象

 */

+ (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;


/**

 *  通过plist来创建一个模型

 *  @param filename 文件名(仅限于mainBundle中的文件)

 *  @return 新建的对象

 */

+ (instancetype)mj_objectWithFilename:(NSString *)filename;


/**

 *  通过plist来创建一个模型

 *  @param file 文件全路径

 *  @return 新建的对象

 */

+ (instancetype)mj_objectWithFile:(NSString *)file;


#pragma mark - 字典数组转模型数组

/**

 *  通过字典数组来创建一个模型数组

 *  @param keyValuesArray 字典数组(可以是NSDictionaryNSDataNSString)

 *  @return 模型数组

 */

+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray;


/**

 *  通过字典数组来创建一个模型数组

 *  @param keyValuesArray 字典数组(可以是NSDictionaryNSDataNSString)

 *  @param context        CoreData上下文

 *  @return 模型数组

 */

+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context;


/**

 *  通过plist来创建一个模型数组

 *  @param filename 文件名(仅限于mainBundle中的文件)

 *  @return 模型数组

 */

+ (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename;


/**

 *  通过plist来创建一个模型数组

 *  @param file 文件全路径

 *  @return 模型数组

 */

+ (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file;


#pragma mark - 转换为JSON

/**

 *  转换为JSON Data

 */

- (NSData *)mj_JSONData;

/**

 *  转换为字典或者数组

 */

- (id)mj_JSONObject;

/**

 *  转换为JSON字符串

 */

- (NSString *)mj_JSONString;



==========*****

"NSObject+MJProperty.h"

******=============

@class MJProperty;


/**

 *  遍历成员变量用的block

 *

 *  @param property 成员的包装对象

 *  @param stop   YES代表停止遍历,NO代表继续遍历

 */

typedef void (^MJPropertiesEnumeration)(MJProperty *property,BOOL *stop);


/** 将属性名换为其他key去字典中取值 */

typedef NSDictionary * (^MJReplacedKeyFromPropertyName)();

typedef NSString * (^MJReplacedKeyFromPropertyName121)(NSString *propertyName);

/** 数组中需要转换的模型类 */

typedef NSDictionary * (^MJObjectClassInArray)();

/** 用于过滤字典中的值 */

typedef id (^MJNewValueFromOldValue)(id object,id oldValue, MJProperty *property);


/**

 * 成员属性相关的扩展

 */

@interface NSObject (MJProperty)

#pragma mark - 遍历

/**

 *  遍历所有的成员

 */

+ (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration;


#pragma mark - 新值配置

/**

 *  用于过滤字典中的值

 *

 *  @param newValueFormOldValue 用于过滤字典中的值

 */

+ (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue;

+ (id)mj_getNewValueFromObject:(__unsafe_unretainedid)object oldValue:(__unsafe_unretainedid)oldValue property:(__unsafe_unretainedMJProperty *)property;


#pragma mark - key配置

/**

 * 将属性名换为其他key去字典中取值(原因:有血后台提供给的字段在oc中是关键字,不能注册为属性,所以就要替换掉)

 *

 *  @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值

 */

+ (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName;

/**

 *  将属性名换为其他key去字典中取值

 *

 *  @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值

 */

+ (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121;


#pragma mark - array model class配置

/**

 *  数组中需要转换的模型类

 *

 *  @param objectClassInArray          数组中需要转换的模型类

 */

+ (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray;

@end



====*******

"NSString+MJExtension.h"========

名称转换

@interface NSString (MJExtension)

/**

 *  驼峰转下划线(loveYou -> love_you

 */

- (NSString *)mj_underlineFromCamel;

/**

 *  下划线转驼峰(love_you -> loveYou

 */

- (NSString *)mj_camelFromUnderline;

/**

 * 首字母变大写

 */

- (NSString *)mj_firstCharUpper;

/**

 * 首字母变小写

 */

- (NSString *)mj_firstCharLower;


- (BOOL)mj_isPureInt;


- (NSURL *)mj_url;


****=================



用MJExtention如果字典中有对应的键名没有在模型中添加成属性,不会奔溃(如果用setvalueforkeysWithDictionary:这个方法会崩溃)。



MJExtention 字典转模型的使用注意



    NSString *path = [[NSBundlemainBundle]pathForResource:@"weibo.json"ofType:nil];

    

    

    NSData *data = [NSDatadataWithContentsOfFile:path];

    

    NSDictionary *dictWeibo = [NSJSONSerialization JSONObjectWithData:dataoptions:0error:nil];

    

    LBWeibo *weibo = [LBWeiBo mj_objectWithKeyValues:dictWeibo];

    

/**

模型中的属性有数组

 *  数组中需要转换的模型类

 *

 *  @return 字典中的key是数组属性名,value是数组中存放模型的ClassClass类型或者NSString类型)

 */如果属性是数组,重写模型方法;

+ (NSDictionary *)objectClassInArray

{

    return@{@"districts" : [DistrictModelclass]};

    //return @{@"districts" : @"DistrictModel"};

}

//CityModel中的属性districts中包含DistrictModel,

NSArray *arr = [CityModelobjectArrayWithFilename:@"cities.plist"];


/**

将idStr换成id去解析:(idStr是模型中的属性)

 *  将属性名换为其他key去字典中取值

 *

 *  @return 字典中的key是属性名,value是从字典中取值用的key

 */用属性名去替换字典中的key

+ (NSDictionary *)mj_replacedKeyFromPropertyName

{

    return@{@"idStr" :@"id"};

}




    //解析比较复杂的json文件的

    //01-用框架

    //02-json中看到字典 就创建模型 模型叫什么?:自己取合适名字模型有哪些属性?看字典中有哪些key

    //03- key名称特殊  ? 或者 属性是数组 ? 重写当前模型的方法  mj_replacedKeyFromPropertyName    mj_objectClassInArray

    //04-属性还是字典 就继续创建模型

    //05-建议从最外层第一个属性开始 一层一层看;


==================
MJExtention中归档的宏定义

MJCodingImplementation

===============================

    //解析比较复杂的json文件的

    //01-用框架

    //02-json中看到字典 就创建模型 模型叫什么?:自己取合适名字模型有哪些属性?看字典中有哪些key

//03- 字典中key名称特殊  ?

用属性名去替换字典中的key

+ (NSDictionary *)mj_replacedKeyFromPropertyName

{

    return@{@"idStr" :@"id"};//用属性idStr替换id

}

 

 如果属性是数组 ?重写当前模型的方法 

+ (NSDictionary *)mj_objectClassInArray

{

    return@{@"annotations" : [CZAnnoDescclass]};//@property (nonatomic,strong)NSArray *annotations;//数组存放特殊的模型数据 CZAnnoDesc

}

 

    //04-属性还是字典 就继续创建模型

    //05-建议从最外层第一个属性开始 一层一层看;

 






0 0
原创粉丝点击