「OC」YYModel的使用方式
「OC」YYModel的使用方式
前言
在我们进行网络请求的过程之中,获取到的JSON数据一般都会被我们封装为一个Model类,而一般来说一个model类之中会有很多个属性,这时候我们在model类进行初始化的时候就会麻烦,我们需要将申请的JSON数据一个一个的赋值给这个Model,非常浪费时间。为了避免如此繁琐的操作,于是我对YYModel进行了相关的学习
JSON与Model简单互换
JSON数据:
// JSON:
{
"name":"bb",
"sex":male,
"grade": 100
}
Model属性
// Model:
@interface Stu : NSObject
@property NSString *sex;
@property NSString *name;
@property NSNumber *grade;
@end
@implementation Stu
@end
对于Model属性名和申请得到的JSON之中的key名字都相同的情况下,我们可以直接使用方法进行互转
// 将 JSON (NSData,NSString,NSDictionary) 转换为 Model:
Stu *stu = [Stu yy_modelWithJSON:json];
// 将 Model 转换为 JSON 对象:
NSDictionary *json = [stu yy_modelToJSONObject];
自动转化
在我们申请到的JSON数据和OC之中对应的数据类型不相一致的时候,YYModel会对这些不同的值自动进行类型转化,以下内容引用大佬博客的内容:
JSON/Dictionary | Model |
---|---|
NSString | NSNumber, NSURL, SEL, Class |
NSNumber | NSString |
NSString/NSNumber | C number (BOOL, int, float, NSUInteger, UInt64, …) |
NaN and Inf | Will be ignored |
NSString | NSDate parsed with these formats: - yyyy-MM-dd - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd’T’HH:mm:ss - yyyy-MM-dd’T’HH:mm:ssZ - EEE MMM dd HH:mm:ss Z yyyy |
NSDate | NSString formatted with ISO8601: |"YYYY-MM-dd’T’HH:mm:ssZ" |
NSValue | Struct (CGRect, CGSize, …) |
NSNull | nil, 0 |
“no”, “false”, … | @(NO), 0 |
Model的属性名和key不相互一致
拿Spotify之中的艺术家JSON信息为例子
//JSON数据
Artist Info:{
"external_urls" = {
spotify = "https://open.spotify.com/artist/1Hu58yHg2CXNfDhlPd7Tdd";
};
followers = {
href = "<null>";
total = 1941449;
};
genres = (
"c-pop",
"classic mandopop"
);
href = "https://api.spotify.com/v1/artists/1Hu58yHg2CXNfDhlPd7Tdd?locale=zh-CN%2Czh-Hans%3Bq%3D0.9";
id = 1Hu58yHg2CXNfDhlPd7Tdd;
images = (
{
height = 640;
url = "https://i.scdn.co/image/ab6761610000e5ebf1496a59885e3470c2644879";
width = 640;
},
{
height = 320;
url = "https://i.scdn.co/image/ab67616100005174f1496a59885e3470c2644879";
width = 320;
},
{
height = 160;
url = "https://i.scdn.co/image/ab6761610000f178f1496a59885e3470c2644879";
width = 160;
}
);
name = "\U5f35\U5b78\U53cb";
popularity = 62;
type = artist;
uri = "spotify:artist:1Hu58yHg2CXNfDhlPd7Tdd";
}
// 艺术家model
#import <Foundation/Foundation.h>
@interface Artist : NSObject
@property (nonatomic, copy) NSString *artistId; // Artist 的 ID
@property (nonatomic, copy) NSString *name; // Artist 名字
@property (nonatomic, copy) NSString *href; // API 路径
@property (nonatomic, copy) NSString *uri; // Spotify URI
@property (nonatomic, assign) NSInteger popularity; // 热度
@property (nonatomic, assign) NSInteger followersTotal; // 追随者数量
@property (nonatomic, strong) NSArray<NSString *> *genres; // 音乐类型
@property (nonatomic, strong) NSArray<NSDictionary *> *images; // 图片信息
@property (nonatomic, copy) NSString *spotifyUrl; // Spotify 链接
@end
我们可以看到model和JSON获取的字典内容并不完全相同,这时候需要我们使用modelCustomPropertyMapper
这个方法,使用一个字典将Model属性名对映射到 JSON 的 Key
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"artistId" : @[@"id",@"ID",@"Artist_id"],
@"followersTotal" : @"followers.total",
@"spotifyUrl" : @"external_urls.spotify"
};
}
如果一个属性没有映射关系,那默认会使用相同属性名作为映射。
在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。
在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。
在不完全相同的情况下,我们可以直接通过在JSON数据之中通过.
来访问JSON数据包含的字典之中的对应属性。
Model之中的嵌套
仍然拿Spotify之中的例子,在我们申请专辑相关信息的时候,会包含相关曲目,以及对应的艺术家,我们都需要对这些相关的model进行存储。
#import <Foundation/Foundation.h>
@class Track,Image;
@class Artist;
NS_ASSUME_NONNULL_BEGIN
@interface Alumb : NSObject
@property (nonatomic, copy) NSString *albumType; // 专辑类型
@property (nonatomic, assign) NSInteger totalTracks; // 歌曲总数
@property (nonatomic, copy) NSString *href; // 链接
@property (nonatomic, copy) NSString *albumId; // 专辑 ID
@property (nonatomic, strong) NSArray<Image *> *images; // 图片列表
@property (nonatomic, copy) NSString *name; // 专辑名称
@property (nonatomic, copy) NSString *releaseDate; // 发行日期
@property (nonatomic, copy) NSString *releaseDatePrecision; // 发行日期精度
@property (nonatomic, copy) NSString *uri; // URI
@property (nonatomic, strong) NSArray<Artist *> *artists; // 艺术家列表
@property (nonatomic, strong) NSArray<Track *> *tracks; // 曲目列表
@property (nonatomic, strong) NSArray<NSDictionary *> *copyrights; // 版权信息
@property (nonatomic, strong) NSDictionary *externalIds; // 外部 ID
@property (nonatomic, strong) NSArray<NSString *> *genres; // 风格
@property (nonatomic, copy) NSString *label; // 唱片公司
@property (nonatomic, assign) NSInteger popularity; // 热度
@property (nonatomic, assign) BOOL isPlayable; // 是否可播放
@end
NS_ASSUME_NONNULL_END
如果是简单的Model嵌套,那么YYModel是会直接帮我们进行转化的,我们不需要进行多余的操作,但是对于上面的情况,我们的Model是用一个容器类进行包装的话,我们就需要重写modelContainerPropertyGenericClass
这个方法返回对应容器之中的Model类型,大致格式如下
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"artists": [Artist class],
@"images": [Image class],
@"tracks": [Track class]
};
}
黑名单和白名单
在我们实际使用YYModel的过程当中,我们可能只需要某个属性或者不需要某个属性,这时候就可以用上黑白名单的功能
// 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
+ (NSArray *)modelPropertyBlacklist {
return @[@"a", @"b"];
}
// 如果实现了该方法,则处理过程中不会处理该列表外的属性。
+ (NSArray *)modelPropertyWhitelist {
return @[@"name",@"ID"];
}
至于YYModel的底层逻辑以及相关源码,会在之后再进行学习。
参考文章
一篇文章全吃透》—YYModel的使用技巧