Coadble是在WWDC2017中发布的 Swift4.0 有一个有趣的新特性,Codable
是Encodable
和Decodable
两个协议的组合,写法如下:
public typealias Codable = Decodable & Encodable
Encodable
这个协议用在那些需要被编码的类型上。如果遵守了这个协议,并且这个类的所有属性都是 Encodable
的, 编译器就会自动的生成相关的实现。如果不是,或者说你需要自定义一些东西,就需要自己实现了。
Decodable
这个协议跟 Encodable
相反,它表示那些能够被解档的类型。跟 Encodable
一样,编译器也会自动为你生成相关的实现,前提是所有属性都是Decodable
的.
这两个协议的实现都很简单,内部都只有一个方法
public protocol Encodable {
func encode(to encoder: Encoder) throws
}
public protocol Decodable {
init(from decoder: Decoder) throws
}
下面使用一个例子来展示Coadble
的用法:
let json = """
{
"firstName": "米饭童鞋",
"points": 200,
"description": "A handsome boy."
}
"""
/// 建立模型
struct Person : Codable {
var firstName: String
var points: Int
var description: String
}
/// JSON 转换为Model
let decoder = JSONDecoder()
// 数组模型转化 (注意:先将json字符串转为data)
let products = try decoder.decode(Person.self, from: json.data(using:.utf8)!)
如果后台返回的JSON
的数据结构比较复杂嵌套的时候,我们可以在struct 里再套一个 struct 来建立模型。
但有时后台系统使用的命名规则有可能与前端不一致,比如后台字段返回下划线命名法,而一般我们使用驼峰命名法,所以在字段映射的时候就需要修改一下,例如后台返回first_name而不是firstName。
let json = """
{
"first_name": "米饭童鞋",
"points": 200,
"description": "A handsome boy."
}
"""
这里有两种解决:
- 实现
CodingKey
协议 进行枚举映射;
/// 只需修改模型,实现CodingKey协议
struct Person : Codable {
var firstName: String
var points: Int
var description: String
/// 自定义字段属性
/// 注意 1.需要遵守Codingkey 2.每个字段都要枚举
private enum CodingKeys: String, CodingKey {
case name = "first_Name"
case points
case description
}
}
- 通过
Decoder
的keyDecodingStrategy
属性, 将属性的值设置为convertFromSnakeCase
,这样我们就不需要写额外的代码处理了,该属性是swift4.1
之后推出的。
/// 只需增加一行代码
let decoder = JSONDecoder()
// 编码策略 使用从蛇形转化为大写 encode时同样也可将驼峰命名法转化为下划线
decoder.keyDecodingStrategy = .convertFromSnakeCase
let products = try decoder.decode(Person.self, from: json.data(using:.utf8)!)
keyDecodingStrategy
是一个枚举值,他还提供了自定义转化规则
public enum KeyDecodingStrategy {
case useDefaultKeys
case convertFromSnakeCase
case custom(([CodingKey]) -> CodingKey) //自定义转化规则
}
let json = """
{
"First_name": "米饭童鞋",
"Points": 200,
"Pescription": "A handsome boy."
}
"""
let decoder = JSONDecoder()
// 自定义转化规则
decoder.keyDecodingStrategy = .custom({ (keys) -> CodingKey in
let lastKey = keys.last!
guard lastKey.intValue == nil else { return lastKey }
// 将首字母大写的转化为小写的
let stringValue = lastKey.stringValue.prefix(1).lowercased() +lastKey.stringValue.dropFirst()
return AnyKey(stringValue: stringValue)!
})
Swift 4 的 Codable 简化我们很多代码。对 JSON 来说, 声明对应的模型来遵守 Codable 协议,然后让编译器做剩下的事情,就完全够了。如果需要,你还可以实现这个协议的某一个部分来满足你自己的需求,甚至你还可以完全自己实现。