如何使用Swift 4为带有动态键的字典数组实现可编码

时间:2019-06-20 06:17:08

标签: ios swift codable decodable

API响应就是这样

  "status": "SUCCESS",
  "mobile": "8856969696",
  "demo": [
    {
      "data1": "some"
    },
    {
      "data2": "value"
    }
  ],
  "pay": "12",
}

我正试图这样解析

struct demoModel : Codable {
    let status: String?
    let mobile: String?
    let demo : [demoData]?
    let pay: String?
    enum CodingKeys: String, CodingKey {

        case status = "status"
        case mobile  = "mobile"
        case demo = "demo"
        case pay = "pay"

    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        status = try values.decodeIfPresent(String.self, forKey: .status)
        mobile  = try values.decodeIfPresent(String.self, forKey: .mobile )
        demo = try values.decodeIfPresent([demoData].self, forKey: .demo)
        pay = try values.decodeIfPresent(String.self, forKey: .pay)

    }

}
struct demoData : Codable {
    let data1: String?

    enum CodingKeys: String, CodingKey {

        case data1 = "data1"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        data1 = try values.decodeIfPresent(String.self, forKey: .data1)
    }

}

此处响应中包含带有动态键的字典数组,请帮助我如何为动态键创建可编码。预先感谢。

3 个答案:

答案 0 :(得分:0)

  

请帮助我如何为动态键创建可编码。

不是Codable协议设计为具有动态密钥,您需要显式声明每个密钥,这对于Codable是不可能的。

对于这些动态键,您必须使用[[String: String]]

以这种方式思考,只要没有与值关联的指定静态键,那么所有内容都将被视为某物的值,因此在您的情况下demo是键,动态字典是您无法解码的最终值,因为解码需要一个密钥才能为其解码值,因此您不能拥有动态密钥。

答案 1 :(得分:0)

尝试这种方式。

class apiResponse{
 var status: String?
 var mobile: String?
 var demo = [[String:Any]]()
 var demoKeys = [String:Any]()

 init(json: [String:Any]){
     self.status = json?["status"] as? String ?? ""
     self.mobile = json?["mobile"] as? String ?? ""
     self.demoKeys = (json?["demo"] as AnyObject) as? [String:Any] ?? [:] 
     for item in demoKeys.keys{
         self.demo.append(json[item] as! [String:Any])
     }
 }
}

答案 2 :(得分:0)

由于demoarray中具有动态键的dictionary,因此您可以简单地使用dictionary类型的[String:String],即

let demo : [[String:String]]?

您只需要创建一个模型即可解析所有数据,即

struct DemoModel : Codable {
    let status: String?
    let mobile: String?
    let demo : [[String:String]]?
    let pay: String?
}

需要注意的地方:

  1. 不需要demoData
  2. 如果模型的属性名称与JSON中的键完全匹配,则无需显式指定enum CodingKeys
  3. 由于您的init(from:)在解析JSON时没有做任何特定的事情,因此您也可以避免这种情况。

您可以使用上述模型来解析数据,例如:

if let data = data {
    do {
        let response = try JSONDecoder().decode(DemoModel.self, from: data)
        print(response)
    } catch {
        print(error)
    }
}