通过 Codable 协议管理动态密钥响应

Managing Dynamic Keys in response through Codable Protocol

我需要为来自响应的字典动态键创建可编码模型,下面是我得到的响应。

{ 
"data" : [
             {
               "desc1" : null,
               "file1" : "uploads\/posts\/Aug-2021\/1629271422310452767"
             },
             {
               "desc2" : "hello",
               "file2" : "uploads\/posts\/Aug-2021\/162927142279356160WhatsApp+Image+2021-07-02+at+12.09.14+PM.jpeg"
             }
         ],
"status" : "success"
}

这个 desc1 和 file1 是动态的,直到像 file1、file2 等等,我需要有可编码的模型,因为下面是我的模型,不支持。

struct ListModel: Codable {
    public var data: [data]?
}
struct data: Codable {
   let file : String?
   let desc : String?
}

可编码协议支持的任何内容。提前致谢。

您需要自定义初始化程序。当然,这只有在您的 json 始终按照描述进行格式化时才有效:

struct File {
    var file: String? = ""
    var desc: String? = ""
}

struct Response {
    let files: [File]
    let status: String
    enum CodingKeys: String, CodingKey {
        case files = "data", status
    }
}

extension Response: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.status = try container.decode(String.self, forKey: .status)
        let elements = try container.decode([[String: String?]].self, forKey: .files)
        self.files = elements.reduce(into: []) {
            var file = File()
            for (key, value) in  {
                if key.hasPrefix("file") {
                    file.file = value
                } else if key.hasPrefix("desc") {
                    file.desc = value
                }
            }
            [=10=].append(file)
        }
    }
}

游乐场测试:

let json = """
{
    "data" : [
                 {
                   "desc1" : null,
                   "file1" : "uploads/posts/Aug-2021/1629271422310452767"
                 },
                 {
                   "desc2" : "hello",
                   "file2" : "uploads/posts/Aug-2021/162927142279356160WhatsApp+Image+2021-07-02+at+12.09.14+PM.jpeg"
                 }
             ],
    "status" : "success"
}
"""

do {
    let response = try JSONDecoder().decode(Response.self, from: Data(json.utf8))
    print(response)
} catch {
    print(error)
}

这将打印:

Response(files: [File(file: Optional("uploads/posts/Aug-2021/1629271422310452767"), desc: nil), File(file: Optional("uploads/posts/Aug-2021/162927142279356160WhatsApp+Image+2021-07-02+at+12.09.14+PM.jpeg"), desc: Optional("hello"))], status: "success")