JSONModel 一個(gè)解析 JSON 數(shù)據(jù)的開(kāi)源庫(kù),可以將 JSON 數(shù)據(jù)直接解析成自定義的 model ,其中對(duì)數(shù)據(jù)類型的檢查和對(duì)數(shù)據(jù)類型的轉(zhuǎn)換比較貼心。最近在項(xiàng)目中使用了以后覺(jué)得確實(shí)方便很多,推薦給大家。(PS:由于實(shí)現(xiàn)的原理在swift中并不支持,所以swift代碼了解就可以)。
國(guó)際慣例介紹下背景,曾經(jīng)有一段時(shí)間一直要寫接口,自然少不了解析獲得的 JSON 數(shù)據(jù),覺(jué)得真的是一種非常機(jī)械重復(fù)的過(guò)程,懵懵懂懂的寫一個(gè)基于 runtime 的解析器,感覺(jué)用起來(lái)方便了不少,但是在錯(cuò)誤處理和一些特殊情況下使用起來(lái)還是覺(jué)得有一些不靈活。多年以后偶然的機(jī)會(huì)又遇到了相同的工作,解析 JSON 數(shù)據(jù),這次選擇了相對(duì)討巧的辦法,使用成熟的開(kāi)源庫(kù)來(lái)解決。想起那句話“知其然,知其所以然”,決定深入的分析下,把我的理解也分享給大家。
先從使用說(shuō)起吧,使用 JSONModel 非常簡(jiǎn)單,只需要將你的 model 類繼承自 JSONModel ,而同時(shí) model 中的屬性名又恰巧可以和 JSON 數(shù)據(jù)中的 key 名字一樣的話,那么非常恭喜你,你的工作已經(jīng)完成90%。如果你還有特殊需求實(shí)際上寫起來(lái)也非常方便,我覺(jué)得完全可以覆蓋日常90%的工作。其他的功能我們會(huì)在分析源碼的時(shí)候看到。
JSONModel 不只使用非常方便而且還會(huì)幫你檢查 JSON 數(shù)據(jù)的完整性,如果 JSON 數(shù)據(jù)不完整的話是要返回 nil 的。它還提供了基本的數(shù)據(jù)類型轉(zhuǎn)換,比如服務(wù)器錯(cuò)將數(shù)字傳成字符串的話 JSONModel 也會(huì)幫你轉(zhuǎn)換成你期望的類型。好啦,廣告做到這里,請(qǐng)相關(guān)部門去收一下廣告費(fèi)。
先看一下文件結(jié)構(gòu),無(wú)視掉網(wǎng)絡(luò)相關(guān)的類是這樣的

既然我們是繼承自JSONModel,那我們就看看JSONModel

頭文件分成三部分: 1) Property protocol 2) AbstractJSONModelProtocol 3) JSONModel
第一部分 Property protocol
@protocol Ignore
@end
我們看到的只是4個(gè)空的協(xié)議 Ignore,Optional,Index,ConvertOnDemand,分別對(duì)應(yīng)的四種使用方法,忽略、可選、排序、延遲加載,粗看起來(lái)貌似都是空的協(xié)議沒(méi)有什么實(shí)際的使用價(jià)值,但是我覺(jué)得正是作者代碼精彩之處,我們都知道在 runtime 系統(tǒng)中,每一個(gè)對(duì)象實(shí)例都有一個(gè)isa指針(PS:新的 runtime 命名可能有些變化,但是原理相通)指向的是該實(shí)例變量的 Class 對(duì)象,進(jìn)而得到該實(shí)例對(duì)象的所有信息。而 JSONModel 正是利用 runtime 系統(tǒng)的這個(gè)特性進(jìn)行解析數(shù)據(jù)的,在Class對(duì)象中我們可以獲得屬性的相關(guān)描述也包括了其符合的協(xié)議,這樣這四個(gè)空協(xié)議就起到了畫(huà)龍點(diǎn)睛的作用,靈活度直線提高。比如在解析JSON的時(shí)候我們發(fā)現(xiàn)其某些屬性符合Igonre就不會(huì)解析該屬性,其他的協(xié)議同理。美中不足由于swift中對(duì)這種機(jī)制支持的并不友好所以JSONModel應(yīng)該不太適用。
還有最后一點(diǎn)作者非常貼心的實(shí)現(xiàn)兩個(gè)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;
四個(gè)初始化方法,實(shí)際上最后都是使用initWithDictionary來(lái)實(shí)現(xiàn)的。具體實(shí)現(xiàn)可以參考代碼
順便提一下instancetype這個(gè)類型是蘋果為了解決我們?cè)诶^承的時(shí)候,返回類型的問(wèn)題,如果你沒(méi)有沒(méi)有遇到或者不了解可以注意下。這樣寫避免了一直被詬病的反悔 id 類型,感興趣可以自己查一下相關(guān)的資料。
還有一些方便的方法暫時(shí)不提,還有幾個(gè)可以重載的方法.
+(JSONKeyMapper*)keyMapper;
keyMapper? 這個(gè)是解決JSON中的key和屬性名字對(duì)應(yīng)不上時(shí)使用的。只對(duì)該類生效
setGlobalKeyMapper 這個(gè)mapper和keyMapper作用一樣只是對(duì)所有的JSONModel的子類都生效的一個(gè)對(duì)應(yīng)關(guān)系
propertyIsOptional 和propertyIsIgnored 是協(xié)議的方法版,設(shè)想你有1000個(gè)屬性要寫明這兩個(gè)協(xié)議你會(huì)不會(huì)瘋掉。也許直接返回一個(gè)YES或者NO就能解決問(wèn)題對(duì)吧。
歡迎來(lái)二一個(gè)灌水
未完待續(xù)