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

时间:2017-11-02 15:21:10

标签: swift xcode enums codable

在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
    }
}

2 个答案:

答案 0 :(得分:3)

struct Foo的每个属性都必须是Codable。这包括MyTypeCodingKey指定将在JSON字典中使用哪些字符串,并且不等同于Codable。 id,name,order字段已经是Codable;由标准库提供。

<强>更新 将此扩展添加到Foo以更改结构字段标签的编码/解码方式为JSON。我随意将my_添加到你的两个属性中。

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

enter image description here

答案 1 :(得分:2)

为什么要使用编码密钥?

  

如果序列化数据格式中使用的密钥与   您的数据类型中的属性名称,提供替代键   将String指定为CodingKeys的原始值类型   枚举。

示例: -

Json -

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

创建符合struct协议的Codable

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)
    }