You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:35:54