***支持swift5.0***
1.swift4出現(xiàn)了Codable協(xié)議,只要繼承該協(xié)議抗楔,便可使用系統(tǒng)的模型轉(zhuǎn)換惯雳,字典轉(zhuǎn)模型已添,模型轉(zhuǎn)字典妥箕。
其實Codable是Decodable協(xié)議和Encodable協(xié)議的歸結(jié)
Codable是這樣定義的:
2.Decodable是用來解檔滥酥,用我的話來說更舞,就是用來Data轉(zhuǎn)換成模型。
我寫了兩種 模型轉(zhuǎn)換的方式:
2.1?一種是定義一個?LsqDecoder 類型坎吻,用于 字典缆蝉、數(shù)組轉(zhuǎn)換成模型:
struct LsqDecoder {
? ? //TODO:轉(zhuǎn)換模型(單個)
? ?public static func decode<T>(_type:T.Type, param: [String:Any]) ->T? where T: Decodable {
? ? ? ? guard let jsonData =self.getJsonData(with: param) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let model = try?JSONDecoder().decode(type, from: jsonData) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return model
? ? }
//多個
public static func decode<T>(_type:T.Type, array: [[String:Any]]) -> [T]? where T: Decodable {
? ? ? ? guard let data =self.getJsonData(with: array) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let models =try? JSONDecoder().decode([T].self, from: data) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return models
? ? }
? ? public static func getJsonData(with param:Any) ->Data? ?{
? ? ? ? if ?!JSONSerialization.isValidJSONObject(param) {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let data =try? JSONSerialization.data(withJSONObject: param, options: []) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return data
? ? }
}
附上截圖:
2.2.一種是延展?Decodable
extension Decodable {
? ? ///dictionary->模型 temp:? Model.decode(dic)
? ? public static func decode(_dictionary: [String:Any]) ->Self? {
? ? ? ? guard let data = self.getJsonData(with: dictionary) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let model =try?JSONDecoder().decode(Self.self, from: data) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return model
? ? }
? ? ///array->模型 temp:[Model].decode(array)
? ? public static func decode(_array: [[String:Any]]) ->Self? {
? ? ? ? guard let data =self.getJsonData(with: array) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let model =try?JSONDecoder().decode(Self.self, from: data) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return model
? ? }
? ? ///JSON->模型
? ? ///此處,本人用了SwiftyJSON用于解析數(shù)據(jù)瘦真,所以添加了該方法刊头,如果沒有使用SwiftyJSON,請注釋或者刪掉以下方法
? ? /*
?? ? 如果是單個诸尽,則 Model.decode(json)
?? ? 如果是多個原杂,則 [Model].decode(json)
?? ? */
? ? public static func decode(_json:JSON) ->Self? ?{
? ? ? ? guard let data =try? json.rawData() else {
? ? ? ? ? ? retur nnil
? ? ? ? }
? ? ? ? guard let model =try?JSONDecoder().decode(Self.self, from: data) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return model
? ? }
? ? public static func getJsonData(with param:Any) -> Data? {
? ? ? ? if ?!JSONSerialization.isValidJSONObject(param) {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let data =try?JSONSerialization.data(withJSONObject: param, options: []) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return data
? ? }
}
附上截圖:
3.好了,看看怎么用吧您机。
例如我有一個這樣的數(shù)據(jù)需要解析:
先寫一個模型穿肄,用來接收數(shù)據(jù)
使用:
如果這里,我只想解析 books际看,又咋整呢咸产?,相當(dāng)于就是數(shù)組轉(zhuǎn)多個模型啦,沒啥區(qū)別仲闽。
好了脑溢,數(shù)據(jù)轉(zhuǎn)模型說完了。
3.下面說說模型歸檔赖欣,有時候需要將模型轉(zhuǎn)換成json屑彻、字典验庙、或者數(shù)組,又該如何呢社牲?這里我也準(zhǔn)備了兩種方案壶谒。
3.1一種是定義一個?LsqEncoder 類型,用于模型轉(zhuǎn)換成字典膳沽、json字符串(集合的沒寫):
//模型轉(zhuǎn)字典汗菜,或轉(zhuǎn)json字符串
struct LsqEncoder {
? ? public static func encoder(toString model:T) ->String? where T: Encodable {
? ? ? ? let encoder =JSONEncoder()
? ? ? ? encoder.outputFormatting = .prettyPrinted
? ? ? ? guard let data =try? encoder.encode(model) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let jsonStr =String(data: data, encoding: .utf8) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return jsonStr
? ? }
? ? public static func encoder(toDictionary model:T) -> [String:Any]? where T: Encodable {
? ? ? ? let encoder =JSONEncoder()
? ? ? ? encoder.outputFormatting = .prettyPrinted
? ? ? ? guard let data =try? encoder.encode(model) else {
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? guard let dict =try?JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String:Any] else{
? ? ? ? ? ? return nil
? ? ? ? }
? ? ? ? return dict
? ? }
}
附上圖片:
3.2 第二種方案挑社,還是延展陨界。
//TODO:模型歸檔
extension Encodable {
? ? public func encoder() ->Data? {
? ? ? ? let ecd =JSONEncoder()
? ? ? ? ecd.outputFormatting = .prettyPrinted
? ? ? ? return try? ?ecd.encode(self)
? ? }
}
extension Data {
? ? ///Data->Dictionary
? ? public func toDictionary() -> [String:Any]? ?{
? ? ? ? return try? JSONSerialization.jsonObject(with: self, options: .mutableLeaves) as? ?[String:Any]
? ? }
? ? ///Data->String
? ? public func toString() ->String? {
? ? ? ? return String(data:self, encoding: .utf8)
? ? }
? ? ///Data->JSON
? ?///本人使用了SwiftyJSON,如未使用SwiftyJSON痛阻,請注釋或刪除以下方法
? ? public func toJSON() ->JSON? ?{
? ? ? ? return JSON(data:self)
? ? }
? ? ///Data->Array
? ? public func toArrray() -> [Any]? {
? ? ? ? return try? JSONSerialization.jsonObject(with: self, options: .mutableLeaves) as? [Any]
? ? }
}
附上圖片:
還是如何使用的問題:我們還是用剛才的數(shù)據(jù)和模型來做示例,但是模型僅僅只實現(xiàn)了Decodable協(xié)議菌瘪,所以,這里要改成
或者:
個人喜好用第二種:
好的阱当,說完了俏扩。