在實際的開發(fā)過程中,我們前臺從后臺獲取json數(shù)據(jù)的時候,要去字典轉(zhuǎn)模型,通常使用一些第三方解決這個問題,如MJExtension,Mantle。
但是后臺返回的數(shù)據(jù)經(jīng)常出現(xiàn)問題,比如下面兩個Json
{"id":"4","nickname":"我是字符串"}
{"id": 4 ,"nickname":"我是數(shù)字類型"}
看到區(qū)別了嗎?就是id這個字段有可能是string類型的,也可能是int類型的,如果在實際的model定義是這個樣子的
#import "BaseModel.h"
@interface THTestModel : BaseModel
/** 用戶id */
@property(nonatomic,copy) NSString * uid;
/** 名字 */
@property(nonatomic,copy) NSString *nickName;
@end
我們將id定義成string類型的uid,但是如果id返回來的數(shù)據(jù)是int,那么第三方一看,類型不對啊,那么就不給你字典轉(zhuǎn)模型,坑死。怎么辦?只能自己去轉(zhuǎn)一下,就是當(dāng)json數(shù)據(jù)一過來,我們就要去判斷,如果是字符串類型的咋辦,如果是NSNumber(使用Mantle裝的時候float,int都認(rèn)為是NSNumber)類型的咋辦。
- .m文件的樣式
#import "THTestModel.h"
@implementation THTestModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey{
return @{
@"uid" :@"id",
@"nickName" :@"nickname"
};
}
+ (NSValueTransformer *)uidJSONTransformer{
return [MTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *string) {
//如果是字符串類型的我們返回他字符串類型
return string;
} reverseBlock:^id(NSNumber *number) {
//NSNumber *number 這個本身是id(id),可以按需更改
//如果是NSnumber類型,我們返回string類型
return [number stringValue];
}];
}
現(xiàn)在這個方法過期了,替換了新的方法,用法一致
+ (NSValueTransformer *)finishedAtAtJSONTransformer{
return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *string, BOOL *success, NSError *__autoreleasing *error) {
//如果是字符串類型的我們返回他字符串類型
return string;
} reverseBlock:^id(NSNumber *number, BOOL *success, NSError *__autoreleasing *error) {
//如果是NSnumber類型,我們返回string類型
return [number stringValue];
}];
}
就是復(fù)寫這個
uidJSONTransformer方法,對類型進(jìn)行判斷處理,就可以解決id類型引發(fā)的問題??墒悄阋欢〞?,為毛線啊,項目沒有搜索到這個方法啊,對,確實沒有,這個方法是屬性名+JSONTransformer,修改誰,去寫對應(yīng)的方法就好,那么nickName叫做nickNameJSONTransformer,可以做對應(yīng)的事情,可以是修改名字,或者對數(shù)據(jù)進(jìn)行更改等
注意!!!
判斷uid是什么類型的時候,Mantle有bug,一定是先去判斷是不是String類型的,然后再去判斷NSNumber類型的,否者奔潰?。?!
會發(fā)生崩潰的寫法
斷點跟著,發(fā)現(xiàn)
@“4”被認(rèn)為是NSNumber *number,執(zhí)行[number stringValue]方法的時候,發(fā)現(xiàn)字符串沒有stringVaule這個方法直接奔潰
//我會崩潰
+ (NSValueTransformer *)uidJSONTransformer{
return [MTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) {
return [number stringValue];
} reverseBlock:^id(NSString *string) {
return string;
}];
}
剛才是對一個屬性分開寫的,很清晰,如果屬性很多,我們也可以“屬性+JSONTransformer”復(fù)寫,非常推薦。
下面在來一個不太推薦的方法(就是將多個屬性放到一個大的方法中去處理判斷,他的名字就是一個):
+ (NSValueTransformer *)JSONTransformerForKey:(NSString *)key{
if ([key isEqualToString:@"uid"]) {
return [MTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *string) {
return string;
} reverseBlock:^id(NSNumber *number) {
return [number stringValue];
}];
}
return nil;
}
注意,還是要先判斷NSString,然后再去判斷NSNumber,否者不會實現(xiàn)字典轉(zhuǎn)模型
ps 正巧,這幾天我們在實際的開發(fā)中,后臺返回來的數(shù)據(jù)好多是有問題的,今天碰巧遇到了,就是返回來的是nil,我們想要一個數(shù)組,好憂傷,不知道怎么辦,好在最后想到了自定義一個方法,最后搞定了,
formatContentJSONTransformer這個方法就是數(shù)據(jù)的預(yù)處理,一定要知道啊~
+ (NSValueTransformer *)formatContentJSONTransformer{
return [MTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSArray *arr) {
//如果是字符串類型的我們返回他字符串類型
if ([arr isKindOfClass:[NSArray class]]) {
return arr;
}else{
return @[];
}
} reverseBlock:^id(id data) {
//NSNumber *number 這個本身是id(id),可以按需更改
//如果是NSnumber類型,我們返回string類型
return @[];
}];
}