自從開始使用Swift作項目,一直都在使用HandyJSON,不能否認,HandyJSON在Swift4.0之前是個好東西,也嘗試過其它json轉mode的工具,最終發現仍是HandyJSON最好用. 去年Swift4.0發佈以後,一個最有趣的變化就是Codable協議. 一直都知道Codable來實現json轉model,不但效率高,而且簡單易用, 可是一直拖到最近才簡單封裝個小工具,爲何呢? 懶😂!!!json
在工具的封裝上,參考了HandyJSON的部分代碼,在使用HandyJSON過程當中,一直都以爲designatedPath
是一個很牛逼的存在,開發效率提高了不是一個量級,因而這裏也參考HandyJSON中designatedPath的實現代碼,並根據Codable的須要改形成fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data?
方法. 在這裏感謝HandyJSON開發組.swift
Codable
擴展所有代碼以下所示.100餘行的代碼先後花費一天多的時間. 當了解到google工程師日均一百多行的代碼量,我以爲這速度還能夠吧. 在代碼質量和閱讀質量上不敢說有多好,我只是按照本身認爲最好的方式來作,若是有哪裏不當或者能夠用更好方法解決的地方,煩請各位告知,彼此交流學習.數組
Codable
協議擴展實現代碼以下所示:ide
// // CodableHelper.swift // CodableDemo // // Created by Walden on 2018/5/7. // Copyright © 2018年 Walden. All rights reserved. // import Foundation //擴展Encodable協議,添加編碼的方法 public extension Encodable { //1.遵照Codable協議的對象轉json字符串 public func toJSONString() -> String? { guard let data = try? JSONEncoder().encode(self) else { return nil } return String(data: data, encoding: .utf8) } //2.對象轉換成jsonObject public func toJSONObject() -> Any? { guard let data = try? JSONEncoder().encode(self) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .allowFragments) } } //擴展Decodable協議,添加解碼的方法 public extension Decodable { //3.json字符串轉對象&數組 public static func decodeJSON(from string: String?, designatedPath: String? = nil) -> Self? { guard let data = string?.data(using: .utf8), let jsonData = getInnerObject(inside: data, by: designatedPath) else { return nil } return try? JSONDecoder().decode(Self.self, from: jsonData) } //4.jsonObject轉換對象或者數組 public static func decodeJSON(from jsonObject: Any?, designatedPath: String? = nil) -> Self? { guard let jsonObject = jsonObject, JSONSerialization.isValidJSONObject(jsonObject), let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []), let jsonData = getInnerObject(inside: data, by: designatedPath) else { return nil } return try? JSONDecoder().decode(Self.self, from: jsonData) } } //擴展Array,添加將jsonString或者jsonObject解碼到對應對象數組的方法 public extension Array where Element: Codable { public static func decodeJSON(from jsonString: String?, designatedPath: String? = nil) -> [Element?]? { guard let data = jsonString?.data(using: .utf8), let jsonData = getInnerObject(inside: data, by: designatedPath), let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [Any] else { return nil } return Array.decodeJSON(from: jsonObject) } public static func decodeJSON(from array: [Any]?) -> [Element?]? { return array?.map({ (item) -> Element? in return Element.decodeJSON(from: item) }) } } /// 借鑑HandyJSON中方法,根據designatedPath獲取object中數據 /// /// - Parameters: /// - jsonData: json data /// - designatedPath: 獲取json object中指定路徑 /// - Returns: 多是json object fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data? { //保證jsonData不爲空,designatedPath有效 guard let _jsonData = jsonData, let paths = designatedPath?.components(separatedBy: "."), paths.count > 0 else { return jsonData } //從jsonObject中取出designatedPath指定的jsonObject let jsonObject = try? JSONSerialization.jsonObject(with: _jsonData, options: .allowFragments) var result: Any? = jsonObject var abort = false var next = jsonObject as? [String: Any] paths.forEach({ (seg) in if seg.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) == "" || abort { return } if let _next = next?[seg] { result = _next next = _next as? [String: Any] } else { abort = true } }) //判斷條件保證返回正確結果,保證沒有流產,保證jsonObject轉換成了Data類型 guard abort == false, let resultJsonObject = result, let data = try? JSONSerialization.data(withJSONObject: resultJsonObject, options: []) else { return nil } return data }
CodableHelper
工具的使用也是很是簡單的,代碼以下所示:工具
//首先定義一個結構體Person用來表示數據Model struct Person: Codable { var name: String? var age: Int? var sex: String? } //1.jsonString中獲取數據封裝成Model let p1String = "{\"name\":\"walden\",\"age\":30,\"sex\":\"man\"}" let p1 = Person.decodeJSON(from: p1String) //2.jsonString中獲取數據封裝成Array let personString = "{\"haha\":[{\"name\":\"walden\",\"age\":30,\"sex\":\"man\"},{\"name\":\"healer\",\"age\":20,\"sex\":\"female\"}]}" let persons = [Person].decodeJSON(from: personString, designatedPath: "haha") //3.對象轉jsonString let jsonString = p1?.toJSONString() //4.對象轉jsonObject let jsonObject = p1?.toJSONObject()
目前存在問題:學習