在 Swift 中,为什么 CodingKey 是我看到的与枚举一起使用的协议,用于在结构上使用 Codable 协议?

In Swift, why is CodingKey the protocol I see being used with enums for use of the Codable protocol on a struct?

在 Swift 中,为什么 CodingKey 是我看到的与枚举一起使用的协议,以便在结构上使用 Codable 协议?

我没有以太多方式对此进行测试,但我一直在尝试复制我找到的所有示例时遇到此错误。通过在枚举上使用 Codable 协议,我得到了完美的行为。

// This throws Error
struct Foo: Codable { //! Type 'Foo' does not conform to protocol 'Codable'

    var id: String
    var name: String
    var type: MyType
    var order: Int

    enum MyType: String, CodingKey {
        case this
        case that
        case and
        case theOtherThing
    }

}

// This doesn't
struct Foo: Codable {

    var id: String
    var name: String
    var type: MyType
    var order: Int

    enum MyType: String, Codable {
        case this
        case that
        case and
        case theOtherThing
    }
}

结构 Foo 的每个 属性 都必须是可编码的。其中包括 MyTypeCodingKey 指定将在 JSON 字典中使用的字符串,不等同于 Codable。 id、name、order 字段已经是 Codable;由标准库提供。

更新 将此扩展添加到 Foo 以更改结构字段标签 encoded/decoded 到 JSON 的方式。我任意将 my_ 添加到您的两个属性中。

extension Foo {
  enum CodingKeys: String, CodingKey {
    case id
    case name
    case type = "my_type"
    case order = "my_order"
  }
}

为什么要使用编码键?

If the keys used in your serialized data format don't match the property names from your data type, provide alternative keys by specifying String as the raw-value type for the CodingKeys enumeration.

示例:-

Json -

    let jsonExample = """
 {
        "id":1,
        "name_Of_person":"jack",
        "emailId":"Demo@apple.com"
}
""".data(using: .utf8)!

创建符合Codable协议的struct

struct UserData: Codable {
    var id: Int
    var name: String
    var email: String
    //Set JSON key values for fields in our custom type
    private enum CodingKeys: String, CodingKey {
        case id //Leave it blank because id matches with json Id
        case name = "name_Of_person"
        case email = "emailId"
    }
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(Int.self, forKey: .id)
        name = try values.decode(String.self, forKey: .name)
        email = try values.decode(String.self, forKey: .email)
    }
}

用法-

 //Decode struct using JSONDecoder

    let jsonDecoder = JSONDecoder()
    do {
        let modelResult = try jsonDecoder.decode(UserData.self,from: jsonExample)
        print("id is \(modelResult.id) - Name is \(modelResult.name) - email is \((modelResult.email))")
    } catch {
        print(error)
    }