Swift中如何使用CodingKeys解析动态JSON键?
Swift Codable 解析动态键对应字段的实现方案
要处理JSON中动态变化的键对应permissions字段的解析,不能依赖自动合成的Codable实现,需要自定义解码逻辑,具体步骤如下:
1. 定义辅助的动态CodingKey
首先创建一个可以适配任意字符串键的CodingKey类型:
struct DynamicCodingKey: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } }
2. 修改Functionality结构体,自定义解码逻辑
将固定字段和动态字段的解析分开处理:
struct Functionality: Codable { let subCod: String? let parentFunctionality: String? let transaccional: String? let permissions: MyModel? // 仅用于固定字段的CodingKey private enum FixedCodingKeys: String, CodingKey { case subCod, parentFunctionality, transaccional } init(from decoder: Decoder) throws { // 1. 解析固定字段 let fixedContainer = try decoder.container(keyedBy: FixedCodingKeys.self) subCod = try fixedContainer.decodeIfPresent(String.self, forKey: .subCod) parentFunctionality = try fixedContainer.decodeIfPresent(String.self, forKey: .parentFunctionality) transaccional = try fixedContainer.decodeIfPresent(String.self, forKey: .transaccional) // 2. 处理动态键的permissions字段 let allContainer = try decoder.container(keyedBy: DynamicCodingKey.self) var tempPermissions: MyModel? // 遍历所有键,排除固定字段后尝试解码为MyModel for key in allContainer.allKeys { // 跳过固定字段的键 guard !FixedCodingKeys.allCases.contains(where: { $0.rawValue == key.stringValue }) else { continue } // 解码该键对应的值为MyModel tempPermissions = try allContainer.decodeIfPresent(MyModel.self, forKey: key) break // 假设仅存在一个动态键对应permissions,找到即退出 } permissions = tempPermissions } }
3. 针对动态键的规则调整(可选)
如果你的动态键有特定规则(比如包含特定字符串、固定前缀等),可以修改遍历逻辑,精准匹配目标键:
// 替换遍历部分的代码,示例:匹配包含"permission"的键 for key in allContainer.allKeys { if key.stringValue.lowercased().contains("permission") { tempPermissions = try allContainer.decodeIfPresent(MyModel.self, forKey: key) break } }
编码支持(可选)
如果需要将结构体编码回JSON,需要自定义encode(to:)方法,注意要存储动态键的名称(可以给结构体添加额外属性permissionsKey: String来记录):
// 修改结构体,添加动态键存储属性 struct Functionality: Codable { let subCod: String? let parentFunctionality: String? let transaccional: String? let permissions: MyModel? let permissionsKey: String // 存储动态键的名称,编码时使用 // ... 省略之前的FixedCodingKeys和init(from:) ... func encode(to encoder: Encoder) throws { // 编码固定字段 var fixedContainer = encoder.container(keyedBy: FixedCodingKeys.self) try fixedContainer.encodeIfPresent(subCod, forKey: .subCod) try fixedContainer.encodeIfPresent(parentFunctionality, forKey: .parentFunctionality) try fixedContainer.encodeIfPresent(transaccional, forKey: .transaccional) // 编码动态键的permissions guard let permissions = permissions else { return } var dynamicContainer = encoder.container(keyedBy: DynamicCodingKey.self) guard let key = DynamicCodingKey(stringValue: permissionsKey) else { return } try dynamicContainer.encode(permissions, forKey: key) } }
内容的提问来源于stack exchange,提问作者DanielColman
相关产品推荐
相关产品推荐

