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
}
基本使用
本文中的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()
})
}
}