Codable 协议

  • Swift
  • 基础

发布于 2019-11-12

Codable 协议能实现基本的序列化和反序列化,Codable 其实是两个协议合一—— Encodable & Decodable

struct User: Codable {
    var name: String
    var age: Int
}

只需要支持 Codable 协议,现在就可以将一个 user 序列化成 JSON 数据

do {
    let user = User(name: "John", age: 31)
    let encoder = JSONEncoder()
    let data = try encoder.encode(user)
} catch {
    print(error)
}

然后我们可以通过 JSONDecoder 进行反序列化

let decoder = JSONDecoder()
let secondUser = try decoder.decode(User.self, from: data)

反序列化出来的 secondUser 应该和一开始我们定义的 user 是相同的,我们也可以看到输出序列化后的 data:

String(data: data, encoding: .utf8)!
// {"name":"John","age":31}

但是有时候我们拿到的 json 不一定和我们定义的结构一致,比如我们拿到的 User JSON 长得像这样

{
    "user_data": {
        "full_name": "John Sundell",
        "user_age": 31
    }
}

一种解决方法是,改我们的 User 结构体使得他符合该 JSON 的格式,当然这种方法优点不切实际。另一种选择我们可以扩展我们 User,添加一个专门用来做序列化和反序列化的类型:

extension User {
    struct CodingData: Codable {
        struct Container: Codable {
      var fullName: String
      var userAge: Int
    }

    var userData: Container
  }
}

然后给 User.CodingData 一个方法用来返回 User 实体

extension User.CodingData {
    var user: User {
        return User(
            name: userData.fullName,
            age: userData.userAge
        )
    }
}

但是我们“键”不一样,但是我们可以通过 keyEncodingStrategykeyDecodingStrategy 来解决这个问题,设置成 convertToSnakeCase 即可

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

let codingData = try decoder.decoder(User.CodingData.self, from: data)
let user = codingData.user

参考文章

  1. Codable | Swift by Sundell

欢迎使用由 Ray Zhao 开发的产品

番茄计

在待办事项的基础上开启番茄钟,更好的查看您的时间管理