Swift4: Codable->字典转模型的具体实现
2018-07-20 本文已影响836人
伯wen
一、字典转模型
- 现有如下JSON数据
let dict: [String : Any] = [
"name" : "zhangsan",
"height" : 1.88,
"pet" : [
"name" : "xiaohei",
"age" : 3
],
"picture": [
[
"url": "这里是url",
"name": "一张图片"
],
[
"url": "这里是url",
"name": "一张图片"
]
]
]
- 根据数据, 定义三个类:
Person
,Pet
,Picture
, 每个类都遵守Codable
协议
class Person: Codable {
var name: String?
var age: Int?
var h: Double?
var pet: Pet?
var picture: [Picture]?
private enum CodingKeys: String, CodingKey {
case h = "height"
case name
case age
case pet
case picture
}
}
class Pet: Codable {
var name: String?
var age: Int?
}
class Picture: Codable {
var url: String?
var name: String?
}
-
Person
类中有如下代码, 表示属性h
接收JSON数据中的height
字段对应的值
private enum CodingKeys: String, CodingKey {
case h = "height"
case name
case age
case pet
case picture
}
- 定义字典转模型方法, 这里使用了泛型
func JSONModel<T>(_ type: T.Type, withKeyValues data:[String:Any]) throws -> T where T: Decodable {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: [])
let model = try JSONDecoder().decode(type, from: jsonData)
return model
}
- 调用字典转模型方法
if let p = try? JSONModel(Person.self, withKeyValues: dict) {
print(p.name, p.h, p.age)
print(p.pet?.name, p.pet?.age)
print(p.picture?.first?.url, p.picture?.first?.name)
}
// 控制台打印:
Optional("zhangsan") Optional(1.8799999999999999) nil
Optional("xiaohei") Optional(3)
Optional("这里是url") Optional("一张图片")
这里类的所有属性都是可选类型, 这是因为当类中的属性, 在JSON数据中没有对应
key
时,
1、如果属性非可选, 就会转模型失败
2、如果属性可选, 这个属性就不会被赋值, 并且模型转换成功
二、数组转模型数组
- 现有如下JSON数组
let list: [[String:Any]] = [
[
"name" : "zhangsan",
"age" : 20
],
[
"name" : "lisi",
"age" : 18
],
[
"name" : "wangwu",
"age" : 25
]
]
- 定义数组转模型数组方法
func JSONModels<T>(_ type: T.Type, withKeyValuesArray datas: [[String:Any]]) throws -> [T] where T: Decodable {
var temp: [T] = []
for data in datas {
let model = try JSONModel(type, withKeyValues: data)
temp.append(model)
}
return temp
}
- 调用数组转模型数组方法
if let ps = try? JSONModels(Person.self, withKeyValuesArray: list) {
for p in ps {
print(p.name, p.age)
}
}
// 控制台打印:
Optional("zhangsan") Optional(20)
Optional("lisi") Optional(18)
Optional("wangwu") Optional(25)
三、上面用到的两个方法
/// 字典 -> 模型
///
/// - Parameters:
/// - type: 类型
/// - data: 字典数据
/// - Returns: 模型结果
/// - Throws: 错误处理
func JSONModel<T>(_ type: T.Type, withKeyValues data:[String:Any]) throws -> T where T: Decodable {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: [])
let model = try JSONDecoder().decode(type, from: jsonData)
return model
}
/// 字典数组 -> 模型数组
///
/// - Parameters:
/// - type: 类型
/// - datas: 字典组数
/// - Returns: 模型数组结果
/// - Throws: 错误处理
func JSONModels<T>(_ type: T.Type, withKeyValuesArray datas: [[String:Any]]) throws -> [T] where T: Decodable {
var temp: [T] = []
for data in datas {
let model = try JSONModel(type, withKeyValues: data)
temp.append(model)
}
return temp
}