***支持swift5.0***
1.swift4出現(xiàn)了Codable協(xié)議,只要繼承該協(xié)議,便可使用系統(tǒng)的模型轉(zhuǎn)換,字典轉(zhuǎn)模型,模型轉(zhuǎn)字典。
其實(shí)Codable是Decodable協(xié)議和Encodable協(xié)議的歸結(jié)
Codable是這樣定義的:

2.Decodable是用來解檔,用我的話來說,就是用來Data轉(zhuǎn)換成模型。
我寫了兩種 模型轉(zhuǎn)換的方式:
2.1?一種是定義一個(gè)?LsqDecoder 類型,用于 字典、數(shù)組轉(zhuǎn)換成模型:
struct LsqDecoder {
? ? //TODO:轉(zhuǎn)換模型(單個(gè))
? ?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
? ? }
//多個(gè)
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,請注釋或者刪掉以下方法
? ? /*
?? ? 如果是單個(gè),則 Model.decode(json)
?? ? 如果是多個(gè),則 [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.好了,看看怎么用吧。
例如我有一個(gè)這樣的數(shù)據(jù)需要解析:

先寫一個(gè)模型,用來接收數(shù)據(jù)

使用:

如果這里,我只想解析 books,又咋整呢?,相當(dāng)于就是數(shù)組轉(zhuǎn)多個(gè)模型啦,沒啥區(qū)別。

好了,數(shù)據(jù)轉(zhuǎn)模型說完了。
3.下面說說模型歸檔,有時(shí)候需要將模型轉(zhuǎn)換成json、字典、或者數(shù)組,又該如何呢?這里我也準(zhǔn)備了兩種方案。
3.1一種是定義一個(gè)?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ù)和模型來做示例,但是模型僅僅只實(shí)現(xiàn)了Decodable協(xié)議,所以,這里要改成

或者:

個(gè)人喜好用第二種:

好的,說完了。