使用Mantle来Model化来自豆瓣的电影数据

Mantle的使用

要实现的功能

我要举得例子来自豆瓣电影,根据某电影ID从豆瓣上把数据抓取出来,通过Mantle格式化为我们需要的Model。

豆瓣电影获取到后是一串JSON,类似下面:

{
    "alt": "http://movie.douban.com/movie/4212172",
    "alt_title": "12生肖",
    "attrs": {
        "cast": [
            "成龙 Jackie Chan",
            "权相宇 Sang-woo Kwone",
            "廖凡 Fan Liao",
            "姚星彤 Xingtong Yao",
            "张蓝心 Lanxin Zhang",
            "白露娜 Laura Weissbecker",
            "刘承俊 Sung-jun Yoo",
            "吴彦祖 Daniel Wu",
            "舒淇 Qi Shu",
            "李宗盛 Jonathan Lee",
            "陈柏霖 Bo-lin Chen",
            "卢惠光 Ken Lo",
            "浅野长英",
            "白冰 Bing Bai",
            "林鹏 Peng Lin"
        ],
        "country": [
            "中国大陆",
            "香港"
        ],
        "director": [
            "成龙 Jackie Chan"
        ],
        "language": [
            "英语",
            "汉语普通话",
            "粤语",
            "法语",
            "西班牙语"
        ],
        "movie_duration": [
            "122分钟"
        ],
        "movie_type": [
            "喜剧",
            "动作",
            "冒险"
        ],
        "pubdate": [
            "2012-12-12(香港国际电影节)",
            "2012-12-20(中国大陆/香港)"
        ],
        "title": [
            "十二生肖"
        ],
        "website": [
            "hbpictures.ayomovie.com/12shengxiao"
        ],
        "writer": [
            "成龙 Jackie Chan",
            "唐季礼 Stanley Tong",
            "邓景生 Edward Tang",
            "陈勋奇 Frankie Chan"
        ],
        "year": [
            "2012"
        ]
    },
    "author": [
        {
            "name": "成龙 Jackie Chan"
        }
    ],
    "id": "http://api.douban.com/movie/4212172",
    "image": "http://img3.douban.com/view/movie_poster_cover/ipst/public/p1826580562.jpg",
    "mobile_link": "http://m.douban.com/movie/subject/4212172/",
    "rating": {
        "average": "6.7",
        "max": 10,
        "min": 0,
        "numRaters": 159114
    },
    "summary": "当年英法联军火烧圆明园,致使大批珍贵文物流落海外,其中四尊十二生肖兽首最引人关注,不仅惹出国内外的广泛争论,更有收藏家开出天价竞拍这几尊珍品。当然,其间不乏奸邪的文物贩子,试图通过偷盗的手段获取宝贝。以此为契机,正在度假的国际大盗JC(成龙 饰)隆重登场。JC背后有一支 Simon(权相宇 饰)、David(廖凡 饰)、Bonnie(张蓝心 饰)等人共同组成的超专业团队,他们一同远赴巴黎,寻求国宝鉴定专家Coco(姚星彤 饰)的帮助。经过周密细致的准备,JC等人一步步逼近重兵把守的兽首,而围绕珍宝不可避免爆发连番惊险火爆的打斗与追逐。
在这一过程中,JC似曾被利益和金钱泯灭的爱国之心渐渐苏醒……",
    "tags": [
        {
            "count": 34460,
            "name": "动作"
        },
        {
            "count": 22094,
            "name": "喜剧"
        },
        {
            "count": 14424,
            "name": "香港"
        },
        {
            "count": 9839,
            "name": "冒险"
        },
        {
            "count": 8222,
            "name": "2012"
        },
        {
            "count": 7660,
            "name": "搞笑"
        },
        {
            "count": 3214,
            "name": "3D"
        },
        {
            "count": 2524,
            "name": "中国大陆"
        }
    ],
    "title": "十二生肖"
}

这个JSON数据可以说是非常复杂的,考虑到了各种情况。数值部分有整数、浮点数、字符串。JSON里面还嵌套有多个Dictionary和Array。

我们要转换的Model定义如下:

// MovieAttrs
@interface DBMovieAttrs: MTLModel<MTLJSONSerializing>

@property (nonatomic, strong) NSArray * cast;
@property (nonatomic, strong) NSArray * country;
@property (nonatomic, strong) NSArray * director;
@property (nonatomic, strong) NSArray * language;
@property (nonatomic, strong) NSArray * movieDuration;
@property (nonatomic, strong) NSArray * movieType;
@property (nonatomic, strong) NSArray * pubdate;
@property (nonatomic, strong) NSArray * title;
@property (nonatomic, strong) NSArray * website;
@property (nonatomic, strong) NSArray * writer;
@property (nonatomic, strong) NSArray * year;

@end

// MovieAuthor
@interface DBMovieAuthor: MTLModel<MTLJSONSerializing>

@property (nonatomic, strong) NSString * name;

@end

// MovieRating
@interface DBMovieRating: MTLModel<MTLJSONSerializing>

@property (nonatomic, strong) NSNumber * average;
@property (nonatomic, assign) NSInteger max;
@property (nonatomic, assign) NSInteger min;
@property (nonatomic, assign) NSInteger numRaters;

@end

// MovieTag
@interface DBMovieTag: MTLModel<MTLJSONSerializing>

@property (nonatomic, assign) NSInteger count;
@property (nonatomic, strong) NSString * name;

@end

// Main
@interface DBMovie: MTLModel<MTLJSONSerializing>

@property (nonatomic, strong) NSURL * alt;
@property (nonatomic, strong) NSString * altTitle;
@property (nonatomic, strong) NSString * movieID;
@property (nonatomic, strong) NSURL * imageURL;
@property (nonatomic, strong) NSURL * mobileLinkURL;
@property (nonatomic, strong) NSString * summary;
@property (nonatomic, strong) NSString * title;

// ==== MovieAttrs
@property (nonatomic, strong) DBMovieAttrs * attrs;
// ==== DBMovieAuthor
@property (nonatomic, strong) NSArray * authors;
// ==== MovieRating
@property (nonatomic, strong) DBMovieRating * rating;
// ==== MovieTag
@property (nonatomic, strong) NSArray * tags;



@end

观察DBMovie中的imageURL属性,是一个NSURL对象。这边有点奇怪,JSON中是不包含特殊数据类型的啊。JSON里面确实没有NSURL,但是我们实际使用的时候肯定是用NSURL,所以为了方便起见,我们会在Model化的时候进行一个转换。而且,通过Mantle这个强大的工具,我们可以很方便的进行这个工作。

MovieAttrsDBMovieAuthorMovieRatingMovieTag都是类对象,都是通过对二级JSON对象的转换得到的。转换方法同NSURL类似。

核心类

Mantle的核心类有3个:

  • MTLModel
  • MTLJSONAdapter
  • MTLJSONSerializing

MTLModel

MTLModel是所有Model的父类,提供了一些默认的行为来处理对象的初始化和归档操作,同时可以获取到对象所有属性的键值集合

MTLJSONAdapter

用于在MTLModel对象和JSON字典之间进行相互转换,相当于是一个适配器

MTLJSONSerializing

需要与JSON字典进行相互转换的MTLModel的子类都需要实现该协议,以方便MTLJSONApadter对象进行转换

实现DBMovie

1 首先根据JSON数据定义写好头文件中的property.

@property (nonatomic, strong) NSURL * alt;
@property (nonatomic, strong) NSString * altTitle;
@property (nonatomic, strong) NSString * movieID;
@property (nonatomic, strong) NSURL * imageURL;
@property (nonatomic, strong) NSURL * mobileLinkURL;
@property (nonatomic, strong) NSString * summary;
@property (nonatomic, strong) NSString * title;

// ==== MovieAttrs
@property (nonatomic, strong) DBMovieAttrs * attrs;
// ==== DBMovieAuthor
@property (nonatomic, strong) NSArray * authors;
// ==== MovieRating
@property (nonatomic, strong) DBMovieRating * rating;
// ==== MovieTag
@property (nonatomic, strong) NSArray * tags;

2 写好Model字段同JSON字段的映射

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{ @"alt"            : @"alt",
              @"altTitle"       : @"alt_title",
              @"movieID"        : @"id",
              @"imageURL"       : @"image",
              @"mobileLinkURL"  : @"mobile_link",
              @"summary"        : @"summary",
              @"title"          : @"title",
              @"attrs"          : @"attrs",
              @"authors"        : @"author",
              @"rating"         : @"rating",
              @"tags"           : @"tags",
              };
}

3 写好特殊字段的处理方法回调函数
回调方法是根据特殊字段名称来命名的,例如imageURL这个字段,它的函数名为:imageURLJSONTransformer

+ (NSValueTransformer *)imageURLJSONTransformer {
    return [MTLValueTransformer valueTransformerForName:MTLURLValueTransformerName];
}

上面的例子使用了内置的转换功能MTLURLValueTransformerName,实际上还有一个内置的转换功能MTLBooleanValueTransformerName

除此之外,如果你要转换一个你自己写的类,那么就应该是用自定义转换,比如我们要转换attrs,它在Model中被映射为DBMovieAttrs类型。

+ (NSValueTransformer *)attrsJSONTransformer {

    return [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) {

        DBMovieAttrs * attrsModel = [MTLJSONAdapter modelOfClass:[DBMovieAttrs class] fromJSONDictionary:value error:nil];

        return attrsModel;
    }];
}

使用Mantle内置的转换函数+ (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)transformation

回调中的value是传递过来的值,一般是一个Dictionary或者Array。返回一个对象,在这边是DBMovieAttrs的对象

4 写好JSON 中null值字段的处理方法回调
在JSON中,如果一个字段没有值,那么值是null,我们在程序中需要特殊处理它,幸运的是Mantle已经为我们考虑好了。你只需要添加一个处理回调函数,即可万无一失。

- (void)setNilValueForKey:(NSString *)key {
    [self setValue:@0 forKey:key];  // For NSInteger/CGFloat/BOOL
}

你可以根据key来设置不同的默认值。非常方便。

写在后面

具体的实现代码可以到这边查看
https://github.com/irobbin1024/Mantle-DoubanMovie

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容