Swift中解码含可变键的JSON:如何定义Codable的Response结构体?
解决Swift中Codable解析动态键顶层JSON的问题
首先,我们先定义对应单个条目的Item结构体,它完美匹配JSON里每个子对象的结构:
struct Item: Codable { let id: String let title: String }
接下来是核心的Response结构体。你的JSON顶层是动态字符串键(唯一ID)对应Item对象的字典,常规固定属性的Codable结构体没法适配这种结构,所以我们通过自定义Codable实现,把顶层字典封装到结构体里,同时还能添加方便的访问方式:
struct Response: Codable { // 存储底层的ID-Item映射字典 private let items: [String: Item] // 计算属性:快速获取所有Item的数组(方便遍历操作) var allItems: [Item] { Array(items.values) } // 下标方法:通过ID直接查找对应的Item,用法更直观 subscript(itemId: String) -> Item? { items[itemId] } // 自定义解码逻辑:直接把顶层完整字典解码到items属性 init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() items = try container.decode([String: Item].self) } // 如果需要把Response再编码回JSON,实现对应的编码逻辑(可选,按需添加) func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(items) } }
解码使用示例
完全按照你要求的方式调用JSONDecoder.decode即可,这里给个完整的测试示例:
// 模拟从API获取的JSON数据(实际场景中替换为真实请求返回的data) let sampleJsonData = """ { "2546": { "id": "2546", "title": "Divis and the Black Mountain" }, "1": { "id": "1", "title": "A la Ronde" }, "2": { "id": "2", "title": "Aberconwy House" } } """.data(using: .utf8)! do { let response = try JSONDecoder().decode(Response.self, from: sampleJsonData) // 输出所有条目 print("所有条目:\(response.allItems)") // 通过ID快速查找特定条目 if let targetItem = response["2546"] { print("ID为2546的条目标题:\(targetItem.title)") } } catch { print("解码出错:\(error.localizedDescription)") }
为什么这么实现?
因为你的JSON顶层没有固定的键名(全是动态生成的唯一ID),常规用CodingKeys绑定固定属性的方式完全不适用。通过singleValueContainer,我们直接把整个顶层字典解码到结构体的内部属性中,既满足了你要求的Response结构体类型,又能完美适配这种动态键的JSON结构。
如果不需要额外的便捷访问方法,你也可以简化Response结构体,只保留核心的编解码逻辑:
struct Response: Codable { // 也可以把items设为public,直接暴露字典给外部使用 public let items: [String: Item] init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() items = try container.decode([String: Item].self) } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(items) } }
内容的提问来源于stack exchange,提问作者Vince O'Sullivan
相关产品推荐
相关产品推荐

