Swift中JSON动态解析:如何根据start字段值获取对应嵌套对象
动态适配JSON中基于start字段的嵌套内容解析(Swift Codable实现)
原始JSON片段
"journey": { "start": "The6422Dcd89Dc070B243Da5743", "6422dcd89dc070b243da5743": { "events": [ { "event_id": "4af5dbc5-b8ae-492d-aa97-16bb9b0967c9", "type": "sale", "name": "SALE" } ] } }
现有硬编码结构体
// MARK: - Journey struct Journey: Codable { let start: String? let value: The6422Dcd89Dc070B243Da5743? let summary: [Summary]? enum CodingKeys: String, CodingKey { case start case value = "6422dcd89dc070b243da5743" case summary } }
解决方案:自定义解码逻辑实现动态适配
要实现动态匹配start字段对应的嵌套内容,需要自定义Codable的解码方法,结合动态CodingKey处理可变键名。
完整实现代码
// MARK: - Journey struct Journey: Codable { let start: String? let value: JourneyContent? let summary: [Summary]? init(from decoder: Decoder) throws { // 解析固定字段start和summary let container = try decoder.container(keyedBy: CodingKeys.self) start = try container.decodeIfPresent(String.self, forKey: .start) summary = try container.decodeIfPresent([Summary].self, forKey: .summary) // 处理动态匹配的嵌套内容 guard let startValue = start else { value = nil return } // 转换start值以匹配JSON中的键:去掉前缀"The"并转为小写 let dynamicKeyString = startValue.lowercased().replacingOccurrences(of: "the", with: "") let dynamicKey = AnyCodingKey(stringValue: dynamicKeyString) // 用动态键解析对应内容 let dynamicContainer = try decoder.container(keyedBy: AnyCodingKey.self) value = try dynamicContainer.decodeIfPresent(JourneyContent.self, forKey: dynamicKey) } enum CodingKeys: String, CodingKey { case start, summary } // 自定义CodingKey,支持任意字符串键 private struct AnyCodingKey: CodingKey { var stringValue: String var intValue: Int? init(stringValue: String) { self.stringValue = stringValue } init?(intValue: Int) { self.intValue = intValue self.stringValue = String(intValue) } } } // 通用的嵌套内容结构体,替代原固定命名结构体 struct JourneyContent: Codable { let events: [Event]? } // Event结构体保持原有解码逻辑 struct Event: Codable { let eventId: String? let type: String? let name: String? enum CodingKeys: String, CodingKey { case eventId = "event_id" case type, name } } // Summary结构体根据实际需求定义字段 struct Summary: Codable { // 示例字段,按需修改 let id: String? }
关键逻辑说明
- 动态CodingKey:定义
AnyCodingKey结构体,允许使用任意字符串作为解码键,摆脱硬编码限制。 - 自定义解码流程:在
init(from decoder: Decoder)中,先解析固定字段start和summary,再通过start的值转换得到动态键,进而解析对应的嵌套内容。 - 结构复用:将原固定命名的嵌套结构体替换为通用的
JourneyContent,适配所有同类结构的动态键内容。
解码测试示例
let testJson = """ { "journey": { "start": "The6422Dcd89Dc070B243Da5743", "6422dcd89dc070b243da5743": { "events": [ { "event_id": "4af5dbc5-b8ae-492d-aa97-16bb9b0967c9", "type": "sale", "name": "SALE" } ] }, "summary": [{"id": "sum_001"}] } } """ do { let data = testJson.data(using: .utf8)! let decoded = try JSONDecoder().decode([String: Journey].self, from: data) guard let journey = decoded["journey"] else { return } print("Start标识:\(journey.start ?? "无")") print("事件数量:\(journey.value?.events?.count ?? 0)") print("Summary数量:\(journey.summary?.count ?? 0)") } catch { print("解码失败:\(error.localizedDescription)") }
内容的提问来源于stack exchange,提问作者Vishnu
相关产品推荐
相关产品推荐

