Swift笔记35:Codable

Codable是编码和解码协议,使开发者更方便的解析JSON 或 plist 文件。支持枚举、结构体和类。

Codable优点是系统原生编解码库,效率高,很多第三方JSON解析都利用到Codable协议。缺点是代码量高,很多编解码解析需要自定义。

Codable协议
typealias Codable = Decodable & Encodable
 
public protocol Decodable {
    public init(from decoder: Decoder) throws
}
 
public protocol Encodable {
    public func encode(to encoder: Encoder) throws
}

查看demo

基本使用

本文中的JSON数据格式
本地文件名:BookList.json

{
  "list": [
    {
      "desc": "资布给回管并转例快真应社斗。需计分很称军次再派非示开。任状般目程公节石达油第易色常表报来。义造手群特做种响必总算政更。能段委百千工则达教图战越。他议她级对和报门各路子至设去见。",
      "name": "蔡平",
      "num": 25
    },
    {
      "desc": "火型己江约统门山强前领周支团京多支。年会选品科还放们约石通次知酸育。团今年县受产共四金识次去号经音统学。当斯几精道口米由究即报热向专较你热。",
      "name": "吴霞",
      "num": 28
    },
}
创建数据模型

模型中提供2个方法
解码(JSON Data -> Model):
let model = try! JSONDecoder().decode(模型.self, from: data)// 解码
/// let decoder = try JSONDecoder()decoder.decode(BookList.self, from: data)
/// let bookDetail = try JSONDecoder().decode(BookDetail.self, from: jsonData)

编码(Model -> JSON Data):
let data = try! JSONEncoder().encode(模型实例) // 编码
let jsonData = JSONEncoder().encode(self)

struct BookList: Codable {
    var list: [BookDetail] // 注意属性中所有类型也要遵守Codable协议

    /// 模型用JSONEncoder的encode转成Data
    /// JSONSerialization反序列化成Dictionary对象

    static func convertFromDict(dict: [String: Any]) -> BookList? {
        var bookList: BookList?
        do {
            let data = try JSONSerialization.data(withJSONObject: dict, options: [])
            let decoder = JSONDecoder()
            bookList = try decoder.decode(BookList.self, from: data)
            print("Success:", bookList as Any)
        } catch {
            print("Error:", error)
        }
        return bookList
    }

    ///
    /// 编码(Model -> JSON Data):
    /// let jsonData = JSONEncoder().encode(user)

    func convertToDict() -> NSDictionary? {
        var dict: NSDictionary?
        do {
            let encoder = JSONEncoder()
            let data = try encoder.encode(self)
            dict = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
        } catch {
            print(error)
        }
        return dict
    }
}

struct BookDetail: Codable {
    var num: Int
    var name: String
    var desc: String
    /// 字典转模型
    static func convertFromDict(dict: [String: Any]) -> BookDetail? {
        var bookDetail: BookDetail?
        do {
            let data = try JSONSerialization.data(withJSONObject: dict, options: [])
            /// 解码(JSON Data -> Model):
            /// let bookDetail = JSONDecoder().decode(BookDetail.self, from: jsonData)
            let decoder = JSONDecoder()
            bookDetail = try decoder.decode(BookDetail.self, from: data)
            print("Success:", bookDetail as Any)
        } catch {
            print("Error:", error)
        }
        return bookDetail
    }

    /// 模型转字典
    /// 编码(Model -> JSON Data):
    /// let jsonData = JSONEncoder().encode(user)

    func convertToDict() -> NSDictionary? {
        var dict: NSDictionary?
        do {
            /// 编码(Model -> JSON Data):
            /// let jsonData = JSONEncoder().encode(self)
            let encoder = JSONEncoder()
            let data = try encoder.encode(self)
            dict = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
        } catch {
            print(error)
        }
        return dict
    }
}

具体应用,网络获取数据后model和字典互转
转换后可以灵活的操作,可以使用点语法或下标访问属性

func getNetModel() {
    let url = GlobalConfig.BOOKLIST_URL
    let parameters = ["key": "value"]
    DispatchQueue.global().async {
        Alamofire.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseJSON(completionHandler: { [weak self] response in
            guard let json = response.result.value, let weakSelf = self else { return }
            let dic = json as? [String: Any]
            guard let dicT = dic else { return }
            guard let arrT = dicT["list"] as? [[String: Any]] else { return }
            let dicM = arrT[0]

            let bookDetail: BookDetail? = BookDetail.convertFromDict(dict: dicM)
            print(">>>>>", bookDetail?.num) // Optional(26)
            print(">>>>>", bookDetail?.name) // Optional("史敏")
            print(">>>>>", bookDetail?.desc) // Optional("即建位表就油见家周心别严通眼等越看)
            let myDic = bookDetail?.convertToDict()
            print("model转换为DIctionary:", myDic) //
        })
    }
}
模型嵌套使用
func getNetModel() {
    let url = GlobalConfig.BOOKLIST_URL
    let parameters = ["key": "value"]
    DispatchQueue.global().async {
        Alamofire.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseJSON(completionHandler: { [weak self] response in
            guard let json = response.result.value, let weakSelf = self else { return }
            guard let dic = json as? [String: Any] else { return }
            let bookList: BookList? = BookList.convertFromDict(dict: dic)
            guard let bookListTemp = bookList?.list else { return }
            weakSelf.bookArray.removeAll()
            weakSelf.bookArray = bookListTemp
            weakSelf.mTableView.reloadData()
        })
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容