YYModel-详细使用

YYModel使用

1.简单的 Model 与 JSON 相互转换

这个很多库都必须的 类似的功能。名字和字典中的键一致


@interface YKUser : NSObject
@property UInt64 uid;
@property NSString *name;
@property NSDate *created;
@end
@implementation YKUser
@end


//数据转模型代码
  NSData *data = [NSData dataNamed:@"twitter_0.json"];
   YKUser *user = [YKUser modelWithJSON:data];

    NSLog(@"%@", user.name);
    NSLog(@"%zd", user.uid);
    NSLog(@"%@", user.created);

JSON/Dictionary 中的对象类型与 Model 属性不一致时,YYModel 将会进行如下自动转换。自动转换不支持的值将会被忽略,以避免各种潜在的崩溃问题。

例子: 如果数据是字符串”no”, 对应到模型中类型不一致就会自动转为0,或者bool类型。 NSNull这样就不用判断class, 空情况了, 直接if(true)就好了。

2.Model 属性名和 JSON 中的 Key 不相同

数据

{
    "n":"Harry Pottery",
    "p": 256,
    "ext" : {
        "desc" : "A book written by J.K.Rowing."
    },
    "ID" : 100010
}

@interface YKUser : NSObject

@property NSString *name;
@property NSInteger page;
@property NSString *desc;
@property NSString *bookID;

@end
@implementation YKUser
+(NSDictionary *)modelCustomPropertyMapper{
    return @{@"name":@"n",
             @"page":@"p",
             @"desc":@"ext.desc",
             @"bookID":@[@"id",@"ID",@"book_id"]
             };
}

@end


//使用
NSData *data = [NSData dataNamed:@"twitter_0.json"];
    YKUser *user = [YKUser modelWithJSON:data];

    NSLog(@"%@", user.desc);

你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。
在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。
在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。

3.Model 包含其他 Model

原始json数据

{
    "author":{
        "name":"J.K.Rowling",
        "birthday":"1965-07-31T00:00:00+0000"
    },
    "name":"Harry Potter",
    "pages":256
}
// Model: 什么都不用做,转换会自动完成
@interface Author : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@implementation Author
@end

@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *author; //Book 包含 Author 属性
@end
@implementation Book
@end


//数据读取
    NSData *data = [NSData dataNamed:@"twitter_0.json"];
    Book *book = [Book modelWithJSON:data];
    NSLog(@"%@", book.author.name);

4.容器类属性

@class Shadow, Border, Attachment;

@interface Attributes
@property NSString *name;
@property NSArray *shadows; //Array<Shadow>
@property NSSet *borders; //Set<Border>
@property NSMutableDictionary *attachments; //Dict<NSString,Attachment>
@end

@implementation Attributes
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
+ (NSDictionary *)modelContainerPropertyGenericClass {
    return @{@"shadows" : [Shadow class],
             @"borders" : Border.class,
             @"attachments" : @"Attachment" };
}
@end

在实际使用过过程中,[Shadow class],Border.class,@”Attachment”没有明显的区别。
这里仅仅是创建作者有说明,实际使用时,需要对其遍历,取出容器中得字典,然后继续字典转模型。(YYModel的核心是通过runtime获取结构体中得Ivars的值,将此值定义为key,然后给key赋value值,所以我们需要自己遍历容器(NSArray,NSSet,NSDictionary),获取每一个值,然后KVC)。

NSDictionary *json =[self getJsonWithJsonName:@"ContainerModel"];
ContainerModel *containModel = [ContainerModel yy_modelWithDictionary:json];
NSDictionary *dataDict = [containModel valueForKey:@"data"];
//定义数组,接受key为list的数组
self.listArray = [dataDict valueForKey:@"list"]; 
 //遍历数组
[self.listArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSDictionary *listDict = obj;
        //获取数组中得字典
        List *listModel = [List yy_modelWithDictionary:listDict];
        //获取count 和 id
        NSString *count = [listModel valueForKey:@"count"];
        NSString *id = [listModel valueForKey:@"id"];

5.黑名单与白名单

@interface User
@property NSString *name;
@property NSUInteger age;
@end

@implementation Attributes
// 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
+ (NSArray *)modelPropertyBlacklist {
    return @[@"test1", @"test2"];
}
// 如果实现了该方法,则处理过程中不会处理该列表外的属性。
+ (NSArray *)modelPropertyWhitelist {
    return @[@"name"];
}
@end

6.数据校验与自定义转换

// JSON:
{
    "name":"Harry",
    "timestamp" : 1445534567     //时间戳
}

// Model:
@interface User
@property NSString *name;
@property NSDate *createdAt;
@end

@implementation User
// 当 JSON 转为 Model 完成后,该方法会被调用。
// 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
// 你也可以在这里做一些自动转换不能完成的工作。
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
    NSNumber *timestamp = dic[@"timestamp"];
    if (![timestamp isKindOfClass:[NSNumber class]]) return NO;
      //相当于自己实现属性赋值
    _createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];
    return YES;
}

// 当 Model 转为 JSON 完成后,该方法会被调用。
// 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
// 你也可以在这里做一些自动转换不能完成的工作。
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
    if (!_createdAt) return NO;
    dic[@"timestamp"] = @(n.timeIntervalSince1970);
    return YES;
}
@end
本文总阅读量