基于ClientType的Swift字典解码:父类与子类Codable实现
解决方案:根据clientType解码包含父类/子类的字典
要实现将JSON中的客户端对象分别解码为Client或SpecialClient实例,你不能直接解码整个[String: Client]类型,需要手动遍历字典中的每个条目,根据clientType字段判断具体类型后再解码。
1. 完善父类与子类的Codable实现
首先确保Client和SpecialClient的Codable逻辑正确,子类要处理自身额外字段并调用父类的解码方法:
class Client: Codable { let clientType: String let label: String enum CodingKeys: String, CodingKey { case clientType, label } } class SpecialClient: Client { let specialValue: Int enum CodingKeys: String, CodingKey { case specialValue } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) specialValue = try container.decode(Int.self, forKey: .specialValue) // 调用父类解码方法处理父类字段 try super.init(from: decoder) } } // 补充JSON中groups对应的模型类 class Group: Codable { let label: String let id: String }
2. 修改Object类的解码逻辑
通过动态键遍历客户端字典,根据clientType选择对应的解码类型:
class Object: Codable { var clients: [String: Client] // 可选:处理JSON中的groups字段 var groups: [String: Group]? enum CodingKeys: String, CodingKey { case clients, groups } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 解析clients字典 let clientsContainer = try container.nestedContainer(keyedBy: DynamicCodingKey.self, forKey: .clients) var clientsDict = [String: Client]() // 遍历所有客户端条目 for key in clientsContainer.allKeys { // 先解码clientType判断类型 let clientTypeContainer = try clientsContainer.nestedContainer(keyedBy: Client.CodingKeys.self, forKey: key) let clientType = try clientTypeContainer.decode(String.self, forKey: .clientType) switch clientType { case "APP": let client = try clientsContainer.decode(Client.self, forKey: key) clientsDict[key.stringValue] = client case "SPECIAL": let specialClient = try clientsContainer.decode(SpecialClient.self, forKey: key) clientsDict[key.stringValue] = specialClient default: throw DecodingError.dataCorruptedError( forKey: key, in: clientsContainer, debugDescription: "未知的客户端类型: \(clientType)" ) } } self.clients = clientsDict // 解析groups字段(可选) self.groups = try container.decodeIfPresent([String: Group].self, forKey: .groups) } } // 辅助类:处理字典的动态字符串键 struct DynamicCodingKey: CodingKey { var stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } }
关键说明
- 动态键处理:使用
DynamicCodingKey适配客户端字典中不确定的键名(如ClientId1、ClientId2) - 类型判断:先解码每个条目的
clientType字段,再决定解码为Client还是SpecialClient - 子类解码:
SpecialClient必须实现required init(from:),先解码自身字段再调用父类的解码方法
内容的提问来源于stack exchange,提问作者rickmcrick
相关产品推荐
相关产品推荐

