Swift:分別使用SwiftyJSON、ObjectMapper、HandyJSON處理JSON


https://www.jianshu.com/p/eeb6c673aeb4

2018.12.21 00:43:33字數 1,947閱讀 2,612

https://www.cnblogs.com/xjf125/p/10704369.html

處理JSON數據是在開發過程中一定會遇到的一項操作,通常情況下我們會先把JSON轉為Dictionary,記住每個數據對應的Key,然后根據這個Key在Dictionary中取出對應的Value值來,那么除了在遇到一些比較復雜的JSON數據時候會顯得有些頭疼和繁瑣之外,可能還會經常出現以下各種錯誤:

因此,為了解決這些問題,很多處理JSON的開源庫應運而生。在Swift中,這些開源庫主要朝着兩個方向努力:

1. 保持JSON語義,直接解析JSON,但通過封裝使調用方式更優雅、更安全;

2. 預定義Model類,將JSON反序列化為類實例,再使用這些實例;

針對以上兩個方向,比較出名的有SwiftyJSONObjectMapperHandyJSON, 下面就根據我個人的開發經驗來分享一下各個框架在處理JSON過程中的使用。

1、SwiftyJSON

  SwiftyJSON的使用相對來說是最廣的, 它是針對上面提到的兩個方向中的第一條產生的一個庫,本質上仍然是根據JSON結構去取值,使用起來比較順手、清晰。

 通常我們拿到數據會進行非常麻煩的Optinonal(可選類型)進行拆包(Wrapping )操作,SwiftyJSON內部會自動對Optinonal進行拆包,大大簡化了代碼,解析非常方便,拿到的Json數據data直接扔進去,例如:

我們不需要考慮服務器返回的是什么類型,比如去請求一個學生的age, 我們想要獲得Int類型或者String類型都可以

通過 .stringValue、 .intValue 就可以獲得不可選值類型,如果沒有獲取到數據的話就會返回一個默認值即 .stringValue獲得空字符串"",.intValue得到 0,.arrayValue獲得空數組[],我們就不用判斷拆包了。除某些特定需要判斷類型的場景除外。

如果我們擁有的是一個JSO格式的字符串,那么:

實際開發中,我們僅僅是對返回的數據進行JSON讀取是不夠的,如果遇到許多地方都用到了 name 值,但是當服務器給我們返回的字段名字改了,我們改項目時就會顯得麻煩,甚至造成修改不完全,所以我們對數據封裝一下轉為模型,這樣修改時只用修改model的一個屬性就可以了 ,  例如:

創建模型,使用Class也可以,但是如果不需要繼承或者不是很復雜,推薦使用結構體struct (可以參考 Swift — struct與class的差異

下面是如何將JSON轉成模型Model 

復雜模型,例如: 

這時候我們就要創建嵌套模型:

這樣就能很方便的取出 scores 里面的值 

以上就是針對 SwiftyJSON 的一些JSON處理

2 、ObjectMapper 

 ObjectMapper不同於SwiftyJSON的是把JSON映射成對象,為了支持映射,ObjectMapper中定義了一個協議,類 class 或者結構體 struct 需要實現Mappable協議, 這個協議包含下面兩個方法:

ObjectMapper使用自定義的 <- 運算符來聲明成員變量和JSON的映射關系,例如:

對象實現了 Mappable、ObjectMapper 就可以輕松的實現JSON 之間的轉換

或者:

或者復雜的數據結構:

ObjectMapper還有很多高級用法,如將model轉換為JSON, 自定義轉換規則等,詳細信息可參考 https://github.com/tristanhimmelman/ObjectMapperhttps://www.hangge.com/blog/cache/detail_1675.html

3、HandyJSON

在使用了SwiftyJSONObjectMapper后會發現,這兩種方法都還是有些缺陷的,首先我們要在model中指明每個屬性對應的字段名,不僅代碼侵入量大,而且拼寫錯誤,后期維護困難,而且Mapping函數要求開發者自定義 

HandyJSON 采用Swift反射+內存賦值的方式來構造Model實例,規避了上述兩個方案遇到的問題,不過HandyJSON也並非完美無缺,如經常造成的內存泄露,兼容性差等問題,所以建議使用最新的HandyJSON庫

Model類想支持通過HandyJSON來反序列化,只需要在定義時,實現HandyJSON協議,這個協議只要求實現一個空的init()函數 

下面就是一個舉例:

假如我們拿到這樣的一個JSON數據,要怎樣來做反序列化呢 

這樣只需調用它的反序列函數就可以了,我們不用再一一指明model屬性對應的字段名稱,也不用擔心定義錯了數據類型。 這是一個比較簡單的JSON轉model, 我們經常會遇到些復雜的JSON數據

開發當中我們還會遇到些嵌套類型的model, 如果model中的某一個屬性是另外一個自定義model,那么只要那個model類也實現了HandyJSON協議,就一樣可以轉換:

有時候服務端返回給我們很多和model無關信息,如 statusCode  , debugMessage等,或者有用的數據是在某個節點以下,那么我們可以指定反序列化哪個節點:

如果某個model類繼承自另一個model類,那么只需要這個父model類實現 HandyJSON 協議就可以

此時我們要注意不能再使用struct,而要使用class創建model

HandyJSON還提供了一個擴展能力,允許自行定義model類某個字段的解析Key、解析方式。

某個Model中,我們不想使用和服務端約定的Key作為屬性名,想自己定一個

有些類型如enum、tuple是無法直接從JSON中解析出來的,但我們在Model類中有這樣的屬性

HandyJSON協議提供了一個可選的mapping()函數,我們可以在其中指定某個字段用什么Key、或者用什么方法從JSON中解析出它的值。如我們有一個model類和一個服務端返回的JSON數據:

我們可以看到,User 的 id 屬性和 json 的Key是對應不上的, 而對於grandpas這個屬性來說,它是一個數組,做不到從json中的 "哈哈, 嘻嘻" 解析出來。所以我們要定義一個Mapping函數來做這兩個支持:

這樣就實現了HandyJSON的自定義解析方式

HandyJSON還支持枚舉屬性,實現支持枚舉,enum 需要實現 HandyJSONEnum 協議

當然,HandyJSON 也提供了把Model類序列化為JSON文本的能力,這里就不做介紹了,詳細方法可以參考: https://github.com/alibaba/handyjson#the-basics    http://www.cnblogs.com/crazyacking/p/5927909.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io#_label00

使用這些庫前要先分別導入SwiftyJSON,ObjectMapper, HandyJSON 如果需要導入的文件很多,那么我們可以挑選一個自己喜歡的文件 @_exported import SwiftyJSON, @_exported import ObjectMapper,@_exported import HandyJSON , 如此只需要導入一次就可以了

關於JSON轉Model的方法就說這么多了,如有什么錯誤希望大家可以指出,有更多的方法也可以補充 。 謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM