使用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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容