gpt4 book ai didi

swift - 为具有失败响应的字典数组实现 Codable

转载 作者:行者123 更新时间:2023-11-28 05:47:22 26 4
gpt4 key购买 nike

我的 JSON 响应如下:

{
"data": [
{
"unknown-key-c3e7f0": {
"date_time": 1546944854000,
"medication": "f4f25ea4-0607-4aac-b85a-edf40cc7d5b6",
"record": {
"status": "never"
}
},
"unknown-key-619d40": {
"date_time": 1546944854000,
"medication": "deef2278-f176-418f-ac34-c65fa54e712c",
"record": {
"status": "always"
}
},
"event": "06b445b9-dae0-48a1-85e4-b9f48c9a2349",
"created": 1546949155020,
"user": "8fb3fcd1-ffe6-4fd9-89b8-d22b1653cb6a",
"id": "1546944855000",
"type": "compliance"
},
{
"unknown-key-619d40": {
"date_time": 1546944975000,
"medication": "deef2278-f176-418f-ac34-c65fa54e712c",
"record": {
"status": "sometimes"
}
},
"event": "7309d8e9-b71c-4068-b278-0ae6d91a57a6",
"created": 1546946798407,
"user": "8fb3fcd1-ffe6-4fd9-89b8-d22b1653cb6a",
"id": "1546944975000",
"type": "compliance"
}
}

从上面的响应中,我想获取未知键及其值。未知键的值是一种名为 Record 的自定义类型,它符合 Codable 协议(protocol)。

我已经为解析数据创建了这个结构

struct RecordSuper: Codable
{
var data: [[String: Record]]
}

因此,我想过滤所有其他键,如 event、created、user 等我在响应中获得的键,并仅保存未知键和值。请建议如何使用 codable 对此进行解析。

我已经阅读了这个答案以及答案的第三条评论中建议的变体。 https://stackoverflow.com/a/46369152/8330469

这个答案展示了如何过滤数组中不正确的数据,以免丢失正确的数据。我正在尝试做类似的事情。

例如,我想丢弃 event 键,因为它是 String 类型而不是 Record 类型。

上面的答案将丢弃整个字典,因为所有字典都有不正确的数据,如 event。最后,我得到一个空数组。

提前致谢。

最佳答案

这是一个广泛基于此 intriguing answer 的解决方案的 Rob Napier .

TitleKey 和两个 Decoder 扩展的目标是将具有任意键的字典映射到数组,并将键添加为 title 属性。

struct TitleKey: CodingKey {
let stringValue: String
init?(stringValue: String) { self.stringValue = stringValue }
var intValue: Int? { return nil }
init?(intValue: Int) { return nil }
}

extension Decoder {
func currentTitle() throws -> String {
guard let titleKey = codingPath.last as? TitleKey else {
throw DecodingError.dataCorrupted(.init(codingPath: codingPath,
debugDescription: "Not in titled container"))
}
return titleKey.stringValue
}
}

extension Decoder {
func decodeTitledElements<Element: Decodable>(_ type: Element.Type) throws -> [Element] {
let titles = try container(keyedBy: TitleKey.self)
return titles.allKeys.compactMap { title in
return try? titles.decode(Element.self, forKey: title)
}
}
}

我修改了 decodeTitledElements 函数以仅解码那些值代表 RecordSuper 结构过滤其他键的字典。

这是结构。

struct Root : Decodable {
let data : [Containers]
}

struct Containers: Decodable {
let containers: [RecordSuper]
init(from decoder: Decoder) throws {
self.containers = try decoder.decodeTitledElements(RecordSuper.self)
}
}

struct RecordSuper : Decodable {
let title : String
let dateTime : Date
let medication : String
let record : Record

enum CodingKeys: String, CodingKey {
case dateTime = "date_time", medication, record
}

init(from decoder: Decoder) throws {
self.title = try decoder.currentTitle()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.dateTime = try container.decode(Date.self, forKey: .dateTime)
self.medication = try container.decode(String.self, forKey: .medication)
self.record = try container.decode(Record.self, forKey: .record)
}
}

struct Record : Decodable {
let status : String
}

现在解码 JSON 假设 jsonData 是作为 Data 的 JSON

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .millisecondsSince1970
let result = try decoder.decode(Root.self, from: jsonData
print(result.data)

关于swift - 为具有失败响应的字典数组实现 Codable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54160875/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com