首頁>技術>

大家過年好,今天的文章來自於讀者的投稿。以下是作者的簡介:

我叫明林清,是的姓明,不姓林。早期做過前端,後來多數時間做 iOS,現在有 10 年多了 ,這幾年在做技術管理,程式碼寫得少了點。現就職於提供音影片直播、點播服務的百家雲。

投稿的內容是作者在春節期間、帶娃之餘、用了幾個晚上完成的一個 Swift 版的 JSON-Model 轉換工具 ExCodable。以下是該專案相關的內容。

別走!看到前面的介紹大家心裡可能想 “嗷,又一個輪子”,但是 ExCodable 真的有點不一樣:

它在 Swift Codable 基礎上做的擴充套件;基於 KeyPath 實現了 Key-Mapping;差不多實現了 YYModel 所有特性;1 個檔案、500 行程式碼。

我們團隊準備開始使用 Swift,第一選擇當然是站在上巨人的肩膀。節前開始尋找一些開源框架,比如網路請求用 Alamofire、自動佈局用 SnapKit,毫無懸念。但是 JSON-Model 轉換並沒有找到一個合適的。

GitHub 上 Star 比較多的有幾種型別:

刀耕火種型:這種框架用於讀寫 JSON,至於 Model 是不管的,比如 SwiftyJSON —— 適用於少量使用、Model 很簡單甚至沒有的情況。優雅紳士型:Swift 內建的 Codable 是可以滿足剛需的,但也有官方框架的通病 —— 繁瑣,Codextended 對其做了大量的簡化,但還是要逐個屬性 Encode/Decode —— 適用於 Model 相對簡單的場景。八仙過海型:ObjectMapper、HandyJSON、KakaJSON 等各有所長,他們都各自構建了整套的序列化、反序列化機制,略複雜,甚至還有直接讀寫記憶體的(“依賴於從 Swift Runtime 原始碼中推斷的記憶體規則,任何變動我們將隨時跟進”),這就有點危險了,至少不夠優雅。

調研一番之後傾向於 Codextended,因為能享受到官方的 Codable。起初有考慮直接基於它做擴充套件來支援 Key-Mapping,但是後來發現受到限制較多,於是重新寫了關鍵部分的實現,有些調整、也有些捨棄。

Codextended 最欠缺的是 Key-Mapping,經過各種摸索、嘗試,發現 KeyPath 方式可行。解決掉關鍵問題後面就簡單了,很快實現了 YYModel 支援的所有特性。

主要特性:

透過 KeyPath 和 CodingKey 配置 Key-Mapping;支援多個候選 Key;支援 Key 巢狀;支援自定義 Encode/Decode Handler;支援使用 Subscript 進行 Encode/Decode;支援型別自動轉換以及自定義轉換;支援多種 Encoder/Decoder,預設使用 JSON,支援 JSON Data、String、Object 三種格式;使用型別推斷;使用 Optional 型別取代拋錯誤;支援 struct、class、subclass。

示例:

定義 struct,使用 var 宣告變數、並設定預設值,可以使用 private(set) 來防止屬性被修改;

struct TestStruct: Equatable {   private(set) var int: Int = 0   private(set) var string: String = ""}

實現 ExCodable,透過 keyMapping 設定 KeyPath 到 CodingKey 的對映,init 和 encode 裡只需一行程式碼;

extension TestStruct: ExCodable {      static var keyMapping: [KeyMap<Self>] = [       KeyMap(\.int, to: "int", "i"),       KeyMap(\.string, to: "nested.string")   ]      init(from decoder: Decoder) throws {       decode(with: Self.keyMapping, using: decoder)   }   func encode(to encoder: Encoder) throws {       encode(with: Self.keyMapping, using: encoder)   }}

Encode、Decode 使用型別推斷,使程式碼更具可讀性;

let test = TestStruct(int: 100, string: "Continue")let data = test.encoded() as Data? // Model to JSON Datalet copy1 = data?.decoded() as TestStruct? // JSON Data to Modellet copy2 = TestStruct.decoded(from: data) // 或者 Model form JSON DataXCTAssertEqual(copy1, test)XCTAssertEqual(copy2, test)

更多示例程式碼參考 GitHub 上的 Usage 以及單元測試程式碼。

在此,需要感謝 John Sundell 的 Codextended 提供的創意;以及 ibireme 的 YYModel 提供的豐富特性。

開源專案地址:https://github.com/iwill/ExCodable

11
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Spring boot整合MQTT做訊息佇列