字典模型轉(zhuǎn)換庫(kù)-MJExtension的使用和原理詳解

? ? 在日常的iOS開(kāi)發(fā)中饿幅,總會(huì)進(jìn)行數(shù)據(jù)的轉(zhuǎn)換险领,比如請(qǐng)求服務(wù)端獲取數(shù)據(jù)侨舆,解析數(shù)據(jù),轉(zhuǎn)換成對(duì)應(yīng)的model绢陌,這個(gè)轉(zhuǎn)換過(guò)程比較繁瑣挨下,重復(fù)工作較多,今天給大家介紹一個(gè)很好用的JSON轉(zhuǎn)換庫(kù)MJExtension脐湾。

? ? MJExtension是一套字典和模型之間互相轉(zhuǎn)換的超輕量級(jí)框架臭笆,利用runtime進(jìn)行數(shù)據(jù)之間的轉(zhuǎn)換,,使用簡(jiǎn)單無(wú)侵入,使用門(mén)檻較低愁铺,下面簡(jiǎn)單介紹下MJExtension的功能鹰霍。

MJExtension的功能介紹

下面是MJExtension的功能,包括將JSON --> Model茵乱,Dictionary -->Model茂洒,Model -->JSON,JSON Array --> Model Array 等等功能瓶竭。

JSON --> Model督勺、Core Data Model

JSONString --> Model、Core Data Model

Model斤贰、Core Data Model --> JSON

JSON Array --> Model Array玷氏、Core Data Model Array

JSONString --> Model Array、Core Data Model Array

Model Array腋舌、Core Data Model Array --> JSON Array

MJExtension的使用

在MJExtension中盏触,我們使用的api都在NSObject+MJKeyValue.h文件中,里面有詳細(xì)的注釋块饺,這里就不多說(shuō)了赞辩。下面我們就用微博的數(shù)據(jù)舉例子,進(jìn)行使用講解

1.簡(jiǎn)單的字典 -> 模型(模型中的屬性都是基本類型)

1)首先我們看下字典轉(zhuǎn)模型,只需要一行代碼就可以授艰,十分簡(jiǎn)潔方便辨嗽,這里需要注意下,model中的對(duì)應(yīng)屬性和字典中的key要相同淮腾,調(diào)用mj_objectWithKeyValues糟需。

字典轉(zhuǎn)模型
User的model

2)假如我們覺(jué)得MJUser中的屬性命名有些歧義,不是很好谷朝,這時(shí)候我們想改一下洲押,比如字典中的name叫jack,可能對(duì)應(yīng)屬性叫firstname更好圆凰,這時(shí)候杈帐,我們就需要在字典轉(zhuǎn)模型的時(shí)候,進(jìn)行屬性名的替換专钉,我們可以這么做挑童,在MJUser.m文件中實(shí)現(xiàn)mj_replacedKeyFromPropertyName方法,方法如下圖所示跃须。

將name用firstname替換
轉(zhuǎn)換過(guò)程替換字典中的key值

3)如果在轉(zhuǎn)換過(guò)程中站叼,我們只想對(duì)部分屬性,進(jìn)行轉(zhuǎn)換菇民,比如尽楔,你只需要firstname和icon投储,name可以使用如下方法進(jìn)行設(shè)置,mj_allowedPropertyNames或者mj_ignoredPropertyNames翔试,這兩個(gè)方法可以看做白名單和黑名單的方法轻要。

mj_allowedPropertyNames和mj_ignoredPropertyNames方法

MJUser.m文件中實(shí)現(xiàn)mj_allowedPropertyNames方法复旬,即可只轉(zhuǎn)換firstname和icon

只轉(zhuǎn)換firstname和icon屬性

4)如果在字典轉(zhuǎn)model的過(guò)程中垦缅,你需要改變firstname的值,在每個(gè) firstname前面加上一段文字驹碍,比如:“jack”變成我是“我的名字是jack”壁涎,這時(shí)候可以使用mj_newValueFromOldValue方法,下面在MJUser.m文件中實(shí)現(xiàn)mj_newValueFromOldValue方法志秃,每次進(jìn)行轉(zhuǎn)換的時(shí)候怔球,都可以在firstname前加上“我的名字是”,或者還可以做一些其它的處理浮还。

在firstname前加上“我的名字是”

5)如果在字典轉(zhuǎn)換為model完成后竟坛,想做一些其它事情,可以使用mj_keyValuesDidFinishConvertingToObject方法進(jìn)行钧舌。

2.復(fù)雜的字典 -> 模型

? ? 除了上面的簡(jiǎn)單字典轉(zhuǎn)模型担汤,還有些復(fù)雜的模型,比如字典中包含字典和數(shù)組洼冻,這種情況崭歧,我們?cè)趺刺幚砟兀孔怖危浚?/p>

1)首先我們看一下率碾,下面這種數(shù)據(jù)結(jié)構(gòu),復(fù)雜的字典 -> 模型 (模型里面包含了模型)

MJStatus的數(shù)據(jù)結(jié)構(gòu)

這是一個(gè)字典嵌套字典的結(jié)構(gòu)屋彪,它需要轉(zhuǎn)成一個(gè)模型嵌套模型的結(jié)構(gòu)

MJStatus的模型

只需要調(diào)用mj_objectWithKeyValues方法即可所宰,跟簡(jiǎn)單模型使用方法一致,其它都不需要我們做畜挥,至于模型嵌套模型這種結(jié)構(gòu)的轉(zhuǎn)換時(shí)怎么實(shí)現(xiàn)的歧匈,我會(huì)在下一部分,講解原理的時(shí)候說(shuō)到砰嘁。

2)下面我們看一下件炉,復(fù)雜的字典 -> 模型 (模型的數(shù)組屬性里面又裝著模型)

模型的數(shù)組屬性里面又裝著模型
MJStatusResult模型

我們可以看到,上面MJStatusResult模型中的statuses屬性和ads屬性矮湘,都是一個(gè)array斟冕,而array中的每一個(gè)元素都是一個(gè)模型,比如statuses中是一個(gè)MJStatus模型缅阳,ads中是MJAd模型磕蛇,在進(jìn)行MJStatusResult模型的轉(zhuǎn)換過(guò)程中景描,我們需要設(shè)置數(shù)組屬性的模型的類型,這時(shí)候我們需要用到mj_objectClassInArray方法秀撇,指定數(shù)組屬性中元素的模型類型超棺,具體用法如下:

statuses的元素是一個(gè)MJStatus,ads中的元素是MJAd

3.模型 -> 字典

模型轉(zhuǎn)字典主要有一下幾個(gè)方法呵燕,用法類似棠绘,這里就不多講了,大家可以看下源碼再扭。

模型轉(zhuǎn)字典的方法

MJExtension的原理

MJExtension中類說(shuō)明

在分析原理之前氧苍,我們先看下文件的MJExtension的文件組成,以及每個(gè)文件的作用泛范。

MJExtension的所有文件

1.MJExtension.h 只是引用了一些頭文件让虐,方便管理。

2.MJExtensionConst.h和MJExtensionConst.m 聲明了一些宏定義罢荡,用來(lái)拋出異常和做判斷用的赡突,同時(shí)聲明和定義了一些屬性類型。

3.MJFoundation.h和MJFoundation.m文件主要是用來(lái)判斷某個(gè)類是否是來(lái)自Foundation庫(kù)中的基本類型区赵,在進(jìn)行字典和模型的轉(zhuǎn)換過(guò)程中惭缰,會(huì)根據(jù)這個(gè)類來(lái)判斷是否是模型嵌套模型的結(jié)構(gòu)。

4.MJProperty.h和MJProperty.m是一個(gè)記錄屬性信息的類惧笛,包含屬性的的所有信息从媚,比如,屬性類型患整,名字拜效,來(lái)源等等。

5.MJPropertyKey.h和MJPropertyKey.m提供一個(gè)根據(jù)屬性key各谚,返回屬性值的方法紧憾。

6.MJPropertyType.h和MJPropertyType.m是記錄一個(gè)屬性的類型,比如MJProperty中屬性類型就是用MJPropertyType來(lái)記錄的昌渤,MJPropertyType類中包含類型標(biāo)識(shí)符赴穗,是否為基本數(shù)字類型,來(lái)源框架膀息,是否支持KVC等等般眉,在字典和模型轉(zhuǎn)換中,提供屬性類型信息潜支。

7.NSObject+MJClass.h和NSObject+MJClass.m用來(lái)遍歷所有類甸赃,并進(jìn)行黑名單和白名單的管理。

8.NSObject+MJCoding.h和NSObject+MJCoding.m主要是對(duì)屬性值進(jìn)行歸檔和解檔冗酿,并且可以對(duì)屬性名字添加黑名單和白名單埠对。

9.NSObject+MJKeyValue.h和NSObject+MJKeyValue.m類中提供了所有模型和字典之間轉(zhuǎn)換的接口络断,上面講的使用方法,都是來(lái)自與這個(gè)類的接口项玛,我們需要熟悉里面的所有接口貌笨,以便可以更好的使用它。

10.NSObject+MJProperty.h和NSObject+MJProperty.m是遍歷模型所有成員襟沮,獲取模型中的屬性锥惋,用MJProperty類保存屬性,用于進(jìn)行字典和模型轉(zhuǎn)換臣嚣。

11.NSString+MJExtension.h和NSString+MJExtension.m是用來(lái)進(jìn)行屬性名字轉(zhuǎn)換的類净刮,比如講駝峰格式的類名剥哑,轉(zhuǎn)換為下劃線的命名格式硅则。

MJExtension模型字典轉(zhuǎn)換過(guò)程

1.使用runtime 獲取模型的所有屬性 ,轉(zhuǎn)換成MJProperty屬性模型列表

2.根據(jù)MJProperty中的屬性類型株婴,對(duì)屬性進(jìn)行處理怎虫,獲取屬性值。

3. 根據(jù)屬性名字困介,通過(guò)KVC對(duì)屬性賦值大审。

1.runtime如何獲取所有屬性

首先我們看下MJExtension的源碼,NSObject+MJProperty類中的+ (NSMutableArray *)properties方法座哩。

通過(guò)Class獲取模型的屬性

1)首先使用runtime中的class_copyPropertyList方法徒扶,獲取類的所有屬性,class_copyPropertyList方法會(huì)返回一個(gè)objc_property_t類型的對(duì)象,這是一個(gè)結(jié)構(gòu)體根穷,如下所示

objc_property

objc_property是一個(gè)結(jié)構(gòu)體姜骡,是一個(gè)內(nèi)置的類型,與之關(guān)聯(lián)的還有一個(gè)objc_property_attribute_t屿良,它是屬性的attribute圈澈,也就是其實(shí)是對(duì)屬性的詳細(xì)描述,包括屬性名稱尘惧、屬性編碼類型康栈、原子類型/非原子類型等。它的定義如下:

objc_property_attribute_t

2)然后遍歷每個(gè)成員喷橙,將objc_property_t中的屬性啥么,轉(zhuǎn)換成MJProperty對(duì)象,轉(zhuǎn)換過(guò)程如下:

objc_property_t轉(zhuǎn)換成MJProperty

首先使用property_getName獲取屬性名贰逾,然后使用property_getAttributes獲取objc_property_attribute_t悬荣,為一個(gè)字符串的結(jié)果,里面包含屬性名稱似踱、屬性編碼類型隅熙、原子類型/非原子類型等稽煤,比如:NSString類型的屬性,對(duì)應(yīng)的attrs為T(mén)@"NSString",C,N,V_icon囚戚。下面我解釋一下這個(gè)字符串對(duì)應(yīng)的意思:

T 表示屬性的類型 類型為基本對(duì)象類型和基本數(shù)據(jù)類型酵熙,基本對(duì)象類型的value為該對(duì)象類型名字 如NSArray、NSString驰坊、NSMutableDictionary 等

C 表示該屬性為copy 匾二;為&表示屬性為strong;W表示屬性為weak拳芙;空 表示屬性為assgin

N表示為非原子屬性

V表示屬性的名字 此時(shí)value為加了下劃線的屬性名字

最后會(huì)根據(jù)property_getAttributes信息生成屬性對(duì)象的type察藐。

2.根據(jù)MJProperty中的屬性類型,對(duì)屬性進(jìn)行處理舟扎,獲取屬性值分飞。

根據(jù)屬性類型,對(duì)屬性進(jìn)行處理主要在- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 方法中進(jìn)行的睹限,如下所示:

對(duì)屬性賦值的過(guò)程

從上面代碼可以看出

1)通過(guò)valueInObject獲取屬性值value譬猫,

2)獲取到值以后,做了一些特殊處理

將value由可變對(duì)象轉(zhuǎn)換成不可變類型

如果value是模型羡疗,則繼續(xù)將value轉(zhuǎn)換成模型染服。

如果模型類型是NSString類型,會(huì)將屬性類型中的NSNumber和NSURL轉(zhuǎn)換為NSString叨恨。

如果模型類型是NSURL類型柳刮,會(huì)將屬性類型中NSString轉(zhuǎn)換為NSURL。

如果模型類型是NSNumber類型痒钝,會(huì)將屬性類型中NSString轉(zhuǎn)換為NSNumber秉颗。

如果模型類型是NSNumber類型,會(huì)將屬性類型中NSString轉(zhuǎn)換為NSNumber午乓。

如果模型類型是BOOL類型站宗,會(huì)將字符串和yes,true益愈,no梢灭,false進(jìn)行匹配,轉(zhuǎn)換為BOOL類型

如果模型類型和屬性類型不匹配蒸其,會(huì)將value設(shè)置為nil敏释。

3. 根據(jù)屬性名字,通過(guò)KVC對(duì)屬性賦值摸袁。

接下來(lái)钥顽,會(huì)使用屬性值value,為屬性賦值靠汁,如下所示:

首先會(huì)判斷是否支持KVC蜂大,如果支持會(huì)給屬性賦值闽铐。

到這里就講解完了MJExtension的使用和原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奶浦,隨后出現(xiàn)的幾起案子兄墅,更是在濱河造成了極大的恐慌,老刑警劉巖澳叉,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隙咸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡成洗,警方通過(guò)查閱死者的電腦和手機(jī)五督,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瓶殃,“玉大人充包,你說(shuō)我怎么就攤上這事÷笛啵” “怎么了误证?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵继薛,是天一觀的道長(zhǎng)修壕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)遏考,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮削樊,結(jié)果婚禮上何什,老公的妹妹穿的比我還像新娘。我一直安慰自己咖楣,他們只是感情好督笆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著诱贿,像睡著了一般娃肿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上珠十,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天料扰,我揣著相機(jī)與錄音,去河邊找鬼焙蹭。 笑死晒杈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孔厉。 我是一名探鬼主播拯钻,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帖努,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了粪般?” 一聲冷哼從身側(cè)響起然磷,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刊驴,沒(méi)想到半個(gè)月后姿搜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捆憎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年舅柜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躲惰。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡致份,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出础拨,到底是詐尸還是另有隱情氮块,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布诡宗,位于F島的核電站滔蝉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏塔沃。R本人自食惡果不足惜蝠引,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛀柴。 院中可真熱鬧螃概,春花似錦、人聲如沸鸽疾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)制肮。三九已至冒窍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弄企,已是汗流浹背超燃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工拘领, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留意乓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓届良,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親士葫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乞而,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容