Swift Codable使用及说明

/ Mac / 没有评论 / 1559浏览

Swift Codable使用及说明

Coadble是在WWDC2017中发布的 Swift4.0 有一个有趣的新特性,CodableEncodableDecodable 两个协议的组合,写法如下:

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."
    }
"""

这里有两种解决:

  1. 实现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
    }
}
  1. 通过DecoderkeyDecodingStrategy属性, 将属性的值设置为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 协议,然后让编译器做剩下的事情,就完全够了。如果需要,你还可以实现这个协议的某一个部分来满足你自己的需求,甚至你还可以完全自己实现。