iOS項目中Json轉(zhuǎn)Model的坑

Json轉(zhuǎn)Model

json轉(zhuǎn)model,是個開發(fā)都會遇到過。都已經(jīng)9102年了,誰還不會用個第三方框架搞。拿起鍵盤就是干!
就是干.png

打開podfile,把大名頂頂?shù)腨YModel寫上,pod install一下。再用上ESJsonFormat,直接根據(jù)json,都能把model生成好。

特殊處理

啥?返回的字段值不是我們所需的
在日常開發(fā)中,經(jīng)常會遇到一些接口字段返回的值,并不是我所需要的類型的情況,這個時候,我們都會對這個字段進(jìn)行處理。
舉個栗子:

/** 錯誤代碼 */
@property (nonatomic, assign) NSInteger error_code;
/** 錯誤消息 */
@property (nonatomic, copy) NSString *error_msg;
/** 是否成功 */
@property (nonatomic, assign) BOOL isSuccess;

接口的json中的error_code字段,接口會用這個字段告訴我這次請求是否成功。比方說成功的error_code是1,平時我們?yōu)榱朔奖汩_發(fā),會在model里自己加一個自定義的屬性isSuccess,來表示本次網(wǎng)絡(luò)請求回來之后的結(jié)果是否成功。通常的做法,要么重寫error_code的set方法,在set的時候,做一次error_code==1的判斷,將判斷的結(jié)果,賦值給isSuccess,要么就重寫isSuccess的get方法,get的時候,返回error_code==1的結(jié)果。
相信這些對于老司機們而言,都屬于常規(guī)操作了。那我們來看看坑在什么地方?

入坑

我們來看這個案例:
接口返回了4個字段值,每個字段都用得到,所以新建一個model類來解析。

@interface ExamSubjectVo : NSObject

/**  考試學(xué)科ID */
@property (nonatomic, assign) NSInteger examSubjectValue;
/**  考試學(xué)科名稱 */
@property (nonatomic, strong) NSString *examSubjectName;
/** 學(xué)科分?jǐn)?shù)  */
@property (nonatomic, strong) NSString *subjectScore;
/** 基礎(chǔ)學(xué)科Id  */
@property (nonatomic, assign) NSInteger subjectBaseId;
@end

但是由于有業(yè)務(wù)需求,且為了方便開發(fā)過程區(qū)分,需要對考試名稱的字段examSubjectName為全科或者語數(shù)外的情況,要特殊處理。所以,按照一貫的思維,我們要重寫set方法

- (void)setExamSubjectName:(NSString *)examSubjectName{
    _examSubjectName = examSubjectName;
    if ([examSubjectName isEqualToString:@"全科"]) {
        self.subjectBaseId = -100;
    }
    if ([examSubjectName isEqualToString:@"語數(shù)外"]) {
        self.subjectBaseId = -200;
    }
}

乍一看,也沒什么問題,解析的過程中,把字段的值轉(zhuǎn)化為我們需要的。而且真機實測的時候,所有的測試機都沒問題,除了一臺iPhone5之外
就除了一臺iPhone5,debug的時候看到set方法確實也走了,可是最終的subjectBaseId并沒有轉(zhuǎn)化成-100或者-200,可見subjectBaseId又被json本身的值覆蓋了,也就是說 set方法的執(zhí)行順序,在不同CPU架構(gòu)設(shè)備上存在差異。

出坑

那么如何解決問題呢?
正是因為存在這樣的差異,所以我們只能在model所有的字段全部set完畢之后,再做一些特殊的字段處理,那么如何來處理呢?
翻閱YYModel源碼,肯定能有所發(fā)現(xiàn),果不其然,有所收獲。

/**
 If the default json-to-model transform does not fit to your model object, implement
 this method to do additional process. You can also use this method to validate the 
 model's properties.
 
 @discussion If the model implements this method, it will be called at the end of
 `+modelWithJSON:`, `+modelWithDictionary:`, `-modelSetWithJSON:` and `-modelSetWithDictionary:`.
 If this method returns NO, the transform process will ignore this model.
 
 @param dic  The json/kv dictionary.
 
 @return Returns YES if the model is valid, or NO to ignore this model.
 */
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;

YYModel提供了這么個方法,它會在+modelWithJSON:, +modelWithDictionary:, -modelSetWithJSON: and -modelSetWithDictionary:方法結(jié)束的時候調(diào)用。
所以我們對model特殊字段的處理,都應(yīng)該放到這個方法去執(zhí)行

- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic{
    if ([self.examSubjectName isEqualToString:@"全科"]) {
        self.subjectBaseId = -100;
    }
    if ([self.examSubjectName isEqualToString:@"語數(shù)外"]) {
        self.subjectBaseId = -200;
    }
    return YES;
}

這么一來,問題就解決了。
注意,YYModel還有一個- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic;
這個方法很類似,但是執(zhí)行的時機不一樣,這個方法是在model轉(zhuǎn)化之前執(zhí)行,雖不符合本案例的需求,但是很有可能在其他類似的情況能用的上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容