Swift为什么定义CodingKeys
Swift为什么定义CodingKeys

Swift为什么定义CodingKeys

Swift 的默认行为是使用属性名称直接作为键名。这种情况下,Codable 的自动合成功能会尝试使用类或结构体的属性名称与 JSON 或其他格式的数据中的键名进行一一对应。

但在某些场景下,这种默认行为可能无法满足需求,因此需要手动定义 CodingKeys。

enum CodingKeys: String, CodingKey {
    case id = "id"
    case name = "name"
}

这部分代码定义了一个枚举,用来表示对象的属性名称在编码和解码过程中与外部数据(如 JSON)的键值映射关系。

Swift 的 Codable 系统在编码和解码时会参考这个枚举,将属性名称和外部数据的键进行映射。

如果属性名称和键名相同,可以省略 = “键名”。

{
    "id": "12345",
    "name": "John Doe"
}

id 会映射到对象的 id 属性。

name 会映射到对象的 name 属性。

不定义 CodingKeys 的情况

默认行为:自动键值映射

如果不定义 CodingKeys,Swift 会直接使用属性的名称作为键。

struct Friend: Codable {
    var id: String
    var name: String
}

let jsonData = """
{
    "id": "001",
    "name": "Alice"
}
""".data(using: .utf8)!

do {
    let decoder = JSONDecoder()
    let friend = try decoder.decode(Friend.self, from: jsonData)
    print(friend) // 输出:Friend(id: "001", name: "Alice")
} catch {
    print("解码失败:\(error)")
}

属性名称与外部数据(如 JSON)的键名完全一致时,无需自定义解码或编码逻辑。

必须定义 CodingKeys 的情况

当键名不匹配时

如果 JSON 数据中的键名与类或结构体的属性名称不同,必须通过 CodingKeys 手动定义映射关系。

例如:

struct Friend: Codable {
    var id: String
    var fullName: String

    enum CodingKeys: String, CodingKey {
        case id
        case fullName = "name"
    }
}

let jsonData = """
{
    "id": "001",
    "name": "Alice"
}
""".data(using: .utf8)!

do {
    let decoder = JSONDecoder()
    let friend = try decoder.decode(Friend.self, from: jsonData)
    print(friend) // 输出:Friend(id: "001", fullName: "Alice")
} catch {
    print("解码失败:\(error)")
}

当需要忽略某些属性时

如果某些属性不需要参与编码或解码,可以通过 CodingKeys 排除它们。例如:

struct Friend: Codable {
    var id: String
    var name: String
    var isAdmin: Bool // 仅用于内部逻辑,不需要编码或解码

    enum CodingKeys: String, CodingKey {
        case id
        case name
    }
}

当需要自定义键的编码或解码方式时

有时可能需要通过 CodingKeys 实现自定义逻辑。例如:

struct Friend: Codable {
    var id: String
    var name: String
    var createdAt: Date

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case createdAt = "created_at"
    }
}

当无法使用自动合成时

如果你需要自定义 init(from:) 或 encode(to:) 的实现,通常也需要定义 CodingKeys。

不定义 CodingKeys 的局限性

无法处理键名不匹配的情况

如果属性名称与外部数据的键名不同,Swift 会抛出解码错误。例如:

struct Friend: Codable {
    var id: String
    var fullName: String // JSON 中的键名是 "name"
}

let jsonData = """
{
    "id": "001",
    "name": "Alice"
}
""".data(using: .utf8)!

do {
    let decoder = JSONDecoder()
    let friend = try decoder.decode(Friend.self, from: jsonData)
    print(friend)
} catch {
    print("解码失败:\(error)") // 解码失败,因为键 "name" 无法匹配 "fullName"
}

无法忽略属性

如果某些属性需要被忽略(不参与编码或解码),不定义 CodingKeys 将导致这些属性也被自动处理。

总结

不定义 CodingKeys

当属性名称与外部数据的键名完全一致时,可以省略 CodingKeys。

自动合成的 Codable 实现会直接使用属性名称作为键名。

需要定义 CodingKeys

属性名称与外部数据键名不同。

某些属性需要忽略。

需要自定义编码或解码逻辑。

JSON 数据或其他外部数据格式需要特殊处理(例如日期格式)。

最佳实践

优先尝试使用 Swift 自动合成的 Codable 功能,但当需要更多的灵活性或处理复杂数据映射时,手动定义 CodingKeys 是必要的。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注