YYModel,相当精简,一个YYClassInfo
类,一个NSObject+YYModel
的分类。
YYClassInfo
是YYModel对类中属性、成员变量、方法和类属性做的一层封装,后面详解会提到。
NSObject+YYModel
工作,就是YYModel的主体工作——JSON转模型。
下面是一个实例:
YYBook *book = [YYBook modelWithJSON:@" \\
{ \\
\\"name\\": \\"Harry Potter\\", \\
\\"pages\\": 512, \\
\\"publishDate\\": \\"2010-01-01\\" \\
}"];
NSObject (YYModel)中,-(instancetype)modelWithJSON:(id)json
分两步:
+ (instancetype)modelWithJSON:(id)json {
NSDictionary *dic = [self _yy_dictionaryWithJSON:json];
return [self modelWithDictionary:dic];
}
(1) 将JSON转换为字典;
_yy_dictionaryWithJSON:
将JSON转换为字典。
+ (NSDictionary *)_yy_dictionaryWithJSON:(id)json {
if (!json || json == (id)kCFNull) return nil;
NSDictionary *dic = nil;
NSData *jsonData = nil;
if ([json isKindOfClass:[NSDictionary class]]) {
dic = json;
} else if ([json isKindOfClass:[NSString class]]) {
jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding];
} else if ([json isKindOfClass:[NSData class]]) {
jsonData = json;
}
if (jsonData) {
dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL];
if (![dic isKindOfClass:[NSDictionary class]]) dic = nil;
}
return dic;
}
kCFNull
Core Foundation 框架中的一个常量,表示一个特殊的空值对象。在 Objective-C 中,它相当于 NSNull,用于表示一个空值或者占位符。kCFNull
是一个单例对象,所以比较时应该使用 ==
而不是 isEqual:
方法。
JSONObjectWithData:jsonData
关于该方法,需要传options,关于options,API说明如下:
//允许json最外层不是NSArray或者NSDictionary
NSJSONReadingMutableContainers = (1UL << 0),
//容器是可变的,解析json返回可变的NSArray和NSDictionary
NSJSONReadingMutableLeaves = (1UL << 1),
//叶子节点是可变的,解析json返回可变的字符串类型
NSJSONReadingAllowFragments = (1UL << 2)
此处用kNilOptions,即0,表示的是返回的可变对象,NSMutableDictionary或MutableNSArray。
如果解析失败,就返回nil;
data参数:支持五种编码格式:UTF-8, UTF-16LE, UTF-16BE, UTF-32LE。效率最高的是UTF-8,所以在此也是用该编码。
(2) 将字典转换为模型。
+ (instancetype)modelWithDictionary:(NSDictionary *)dictionary {
if (!dictionary || dictionary == (id)kCFNull) return nil;
if (![dictionary isKindOfClass:[NSDictionary class]]) return nil;
//!!!忽略 这部分不是转model的过程,只是在自定义了转化为自定义类时,需要获取该自定义的类。
Class cls = [self class]; //cls:YYBook
_YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:cls];
if (modelMeta->_hasCustomClassFromDictionary) {
cls = [cls modelCustomClassForDictionary:dictionary] ?: cls;
}
NSObject *one = [cls new];
if ([one modelSetWithDictionary:dictionary]) return one;
return nil;
}
字典转模型过程如下:
modelCustomClassForDictionary
,那么先获取类信息。modelCustomClassForDictionary
方法提供了我们在字典转模型
的过程中创建不同类型对象的途径:比如,要初始化一个Shape类对象,根据是否有对应字段来生成不同的子类: