JSONModel 一個解析 JSON 數(shù)據(jù)的開源庫,可以將 JSON 數(shù)據(jù)直接解析成自定義的 model ,其中對數(shù)據(jù)類型的檢查和對數(shù)據(jù)類型的轉(zhuǎn)換比較貼心。最近在項目中使用了以后覺得確實(shí)方便很多,推薦給大家。(PS:由于實(shí)現(xiàn)的原理在swift中并不支持,所以swift代碼了解就可以)。
國際慣例介紹下背景,曾經(jīng)有一段時間一直要寫接口,自然少不了解析獲得的 JSON 數(shù)據(jù),覺得真的是一種非常機(jī)械重復(fù)的過程,懵懵懂懂的寫一個基于 runtime 的解析器,感覺用起來方便了不少,但是在錯誤處理和一些特殊情況下使用起來還是覺得有一些不靈活。多年以后偶然的機(jī)會又遇到了相同的工作,解析 JSON 數(shù)據(jù),這次選擇了相對討巧的辦法,使用成熟的開源庫來解決。想起那句話“知其然,知其所以然”,決定深入的分析下,把我的理解也分享給大家。
先從使用說起吧,使用 JSONModel 非常簡單,只需要將你的 model 類繼承自 JSONModel ,而同時 model 中的屬性名又恰巧可以和 JSON 數(shù)據(jù)中的 key 名字一樣的話,那么非常恭喜你,你的工作已經(jīng)完成90%。如果你還有特殊需求實(shí)際上寫起來也非常方便,我覺得完全可以覆蓋日常90%的工作。其他的功能我們會在分析源碼的時候看到。
JSONModel 不只使用非常方便而且還會幫你檢查 JSON 數(shù)據(jù)的完整性,如果 JSON 數(shù)據(jù)不完整的話是要返回 nil 的。它還提供了基本的數(shù)據(jù)類型轉(zhuǎn)換,比如服務(wù)器錯將數(shù)字傳成字符串的話 JSONModel 也會幫你轉(zhuǎn)換成你期望的類型。好啦,廣告做到這里,請相關(guān)部門去收一下廣告費(fèi)。
先看一下文件結(jié)構(gòu),無視掉網(wǎng)絡(luò)相關(guān)的類是這樣的
既然我們是繼承自JSONModel,那我們就看看JSONModel
頭文件分成三部分: 1) Property protocol 2) AbstractJSONModelProtocol 3) JSONModel
第一部分 Property protocol
@protocol Ignore
@end
我們看到的只是4個空的協(xié)議 Ignore,Optional,Index,ConvertOnDemand,分別對應(yīng)的四種使用方法,忽略、可選、排序、延遲加載,粗看起來貌似都是空的協(xié)議沒有什么實(shí)際的使用價值,但是我覺得正是作者代碼精彩之處,我們都知道在 runtime 系統(tǒng)中,每一個對象實(shí)例都有一個isa指針(PS:新的 runtime 命名可能有些變化,但是原理相通)指向的是該實(shí)例變量的 Class 對象,進(jìn)而得到該實(shí)例對象的所有信息。而 JSONModel 正是利用 runtime 系統(tǒng)的這個特性進(jìn)行解析數(shù)據(jù)的,在Class對象中我們可以獲得屬性的相關(guān)描述也包括了其符合的協(xié)議,這樣這四個空協(xié)議就起到了畫龍點(diǎn)睛的作用,靈活度直線提高。比如在解析JSON的時候我們發(fā)現(xiàn)其某些屬性符合Igonre就不會解析該屬性,其他的協(xié)議同理。美中不足由于swift中對這種機(jī)制支持的并不友好所以JSONModel應(yīng)該不太適用。
還有最后一點(diǎn)作者非常貼心的實(shí)現(xiàn)兩個Category為了防止編譯器的警告,大家也可以參考一下這種寫法。
第二部分 AbstractJSONModelProtocol
是 JSONModel 符合的抽象協(xié)議。如果你的類也符合該協(xié)議, 可以理解于是和JSONModel一樣的,可以將不繼承自 JSONModel 的類當(dāng)作屬性一起解析,一般還是推薦繼承自 JSONModel 不然里面很多細(xì)節(jié)都要你自己去實(shí)現(xiàn)。
第三部分 JSONModel
-(instancetype)initWithString:(NSString*)string error:(JSONModelError**)err;
-(instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError**)err;
-(instancetype)initWithDictionary:(NSDictionary*)dict error:(NSError **)err;
-(instancetype)initWithData:(NSData *)data error:(NSError **)error;
四個初始化方法,實(shí)際上最后都是使用initWithDictionary來實(shí)現(xiàn)的。具體實(shí)現(xiàn)可以參考代碼
順便提一下instancetype這個類型是蘋果為了解決我們在繼承的時候,返回類型的問題,如果你沒有沒有遇到或者不了解可以注意下。這樣寫避免了一直被詬病的反悔 id 類型,感興趣可以自己查一下相關(guān)的資料。
還有一些方便的方法暫時不提,還有幾個可以重載的方法.
+(JSONKeyMapper*)keyMapper;
keyMapper? 這個是解決JSON中的key和屬性名字對應(yīng)不上時使用的。只對該類生效
setGlobalKeyMapper 這個mapper和keyMapper作用一樣只是對所有的JSONModel的子類都生效的一個對應(yīng)關(guān)系
propertyIsOptional 和propertyIsIgnored 是協(xié)議的方法版,設(shè)想你有1000個屬性要寫明這兩個協(xié)議你會不會瘋掉。也許直接返回一個YES或者NO就能解決問題對吧。
歡迎來二一個灌水
未完待續(xù)