围绕 Swift Codable
实现的一系列扩展。
Swift 中的 Any
类型不符合 Codable
协议,因为它能表示任何类型(无论是否可编码)。但是,我们会在某些情况下遇到 JSON 对象由 Dictionary<String, Any>
表示的情况,这里的 Any 被限制为一组已知的、支持 codable 的类型。
现在可以将 JSON 对象反序列化/序列化为/从它们的 swift 对等物。一个可能使用这种情况的主要例子是 API,它们可能期望一个“合理”定义的响应,但可能会使用随机或运行时未知的键。在这种情况下,类型安全无法满足,但数据仍然有价值。
现在可以与以下 Container
定义和 JSON 代码片段进行交互
struct Container: Codable {
var dictionary: [String: Any]
private enum CodingKeys: String, CodingKey {
case dictionary
}
init(dictionary: [String: Any]) {
self.dictionary = dictionary
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
dictionary = try container.decode([String: Any].self, forKey: .dictionary)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(dictionary, forKey: .dictionary)
}
}
{
"dictionary": {
"aString": "This is a string.",
"aInt": 47,
"aDouble": 55.88,
"aBool": true,
"aArray": ["String", 123, 123.456, false],
"aDictionary": {
"name": "Bob",
"age": 69
}
}
}
这些相同的示例可以应用于 Array<Any>
,其中 Any 表示 JSON 兼容的原语之一
字符串
整数
双精度浮点数
布尔值
以及这些容器,当由相同的原始类型组成时。
数组
字典
在项目的积极开发期间,API 规范经常会更改,或者可能在一个端点到另一个端点之间不一致。如果我们的 Swift 模型可以保持一致,但支持解码多个可能的实体模型,那将非常方便。使用 Codable+,这是可能的。
给定以下内容
struct CompanyV1: Decodable {
var name: String
var employees: Int
}
struct CompanyV2: Decodable {
var companyName: String
var employees: Int
var ceoName: String
private enum CodingKeys: String, CodingKey {
case name
case companyName
case employees
case ceoName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
companyName = try container.decode(String.self, forKeys: [.name, .companyName])
employees = try container.decode(Int.self, forKey: .employees)
ceoName = try container.decodeIfPresent(String.self, forKey: .ceoName) ?? ""
}
}
let schema1json = """
{
"name": "Apple",
"employees": 42000
}
"""
let schema2json = """
{
"companyName": "Microsoft",
"employees": 600000,
"ceoName": "Satya Nadella"
}
"""
注意到 init(from:)
方法中的 companyName =
吗?这指定了多个可能的 CodingKey
。现在我们的 CompanyV2
模型支持解码我们的 CompanyV1
模式。
Codable+ 使用 Swift Package Manager 分发。要将其安装到项目中,请将其作为依赖项添加到您的 Package.swift
清单中
let package = Package(
...
dependencies: [
.package(url: "https://github.com/richardpiazza/CodablePlus.git", from: "1.0.0")
],
...
)
然后在您想要使用它的任何地方导入 Codable+
import CodablePlus
Codable+ 的发展和灵感来源于互联网上的一些帖子