使用Codable解析含动态键的JSON数据问题求助
动态键名场景下的Codable模型实现
当JSON中某字段的键名动态变化且非数组时,核心解决思路是用字典类型承接动态键值对,同时保留Codable的类型安全特性。以下是具体实现方案:
1. 定义子项结构体
先把动态键对应的统一子数据结构定义为Codable结构体。假设你的JSON示例结构如下(可根据实际调整):
{ "code": 200, "data": { "dynamic_key_001": {"title": "商品A", "price": 99}, "dynamic_key_002": {"title": "商品B", "price": 199} } }
对应的子项结构体:
struct Product: Codable { let title: String let price: Int }
2. 定义顶层响应模型
将data字段声明为[String: Product]类型,这样就能适配任意动态键名:
struct ApiResponse: Codable { let code: Int let data: [String: Product] }
3. 解析本地JSON文件示例
// 读取本地JSON文件 guard let fileURL = Bundle.main.url(forResource: "sample", withExtension: "json"), let jsonData = try? Data(contentsOf: fileURL) else { print("读取本地JSON失败") return } // 解析模型 do { let response = try JSONDecoder().decode(ApiResponse.self, from: jsonData) // 遍历动态键值对 for (key, product) in response.data { print("键名:\(key),商品名:\(product.title),价格:\(product.price)") } } catch { print("解析错误:\(error.localizedDescription)") }
特殊场景处理
如果动态键对应的子结构不统一(比如有的子项有title,有的有desc),可以选择两种方式:
- 方式一:用
[String: [String: Any]]作为data类型,但会失去类型安全,仅适用于临时调试。 - 方式二:自定义Codable解析逻辑,在
init(from decoder: Decoder)中根据子结构的特征判断解析类型,示例如下:
struct ApiResponse: Codable { let code: Int let data: [String: BaseItem] enum CodingKeys: String, CodingKey { case code, data } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) code = try container.decode(Int.self, forKey: .code) let dataContainer = try container.container(keyedBy: DynamicCodingKey.self, forKey: .data) var items = [String: BaseItem]() for key in dataContainer.allKeys { let keyString = key.stringValue if let product = try? dataContainer.decode(Product.self, forKey: key) { items[keyString] = product } else if let article = try? dataContainer.decode(Article.self, forKey: key) { items[keyString] = article } } data = items } } // 动态CodingKey实现 struct DynamicCodingKey: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } } // 不同子项结构体 protocol BaseItem: Codable {} struct Product: BaseItem { let title: String; let price: Int } struct Article: BaseItem { let desc: String; let readCount: Int }
内容的提问来源于stack exchange,提问作者green8
相关产品推荐
相关产品推荐

