Swift中Codable如何处理包含多种数据模型的Any类型字段
优化方案
你当前实现存在两个核心问题:
Any类型不兼容Codable协议,后续如果需要将OverviewWorkout实例做序列化操作会直接报错- 后续使用
data字段时需要手动做类型判断和强转,代码冗余且容易出现类型转换错误
推荐你用带关联值的枚举替代Any类型来包裹不同格式的data字段,完全适配你的业务场景,改造后的代码如下:
import Foundation struct OverviewWorkout : Codable { enum WorkoutType: String, Codable { case workout case coach case bodyArea case challenge case title case group case trainer } // 用带关联值的枚举统一包裹所有可能的data类型 enum WorkoutData: Codable { case singleWorkout(Workout) case coachInstruction(CoachInstruction) case workoutList([Workout]) case title(Title) case trainerList([Trainer]) } var type: WorkoutType var data : WorkoutData init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) type = try container.decode(WorkoutType.self, forKey: .type) switch type { case .workout, .challenge: data = .singleWorkout(try container.decode(Workout.self, forKey: .data)) case .coach: data = .coachInstruction(try container.decode(CoachInstruction.self, forKey: .data)) case .bodyArea, .group: data = .workoutList(try container.decode([Workout].self, forKey: .data)) case .title: data = .title(try container.decode(Title.self, forKey: .data)) case .trainer: data = .trainerList(try container.decode([Trainer].self, forKey: .data)) } } private enum CodingKeys: String, CodingKey { case type,data } } extension OverviewWorkout { struct Title: Codable { let title: String } }
改造后的代码优势:
- 完全兼容
Codable协议,解码、编码都能正常执行 - 类型安全,后续使用data时不需要强制类型转换,直接匹配枚举的关联值即可拿到对应类型的模型:
// 调用示例 let overviewData: OverviewWorkout = ... switch overviewData.data { case .singleWorkout(let workout): // 直接使用Workout类型的workout实例 case .coachInstruction(let coach): // 直接使用CoachInstruction类型的coach实例 // 其他类型匹配逻辑 } - 后续新增data类型只需要在
WorkoutData枚举里新增对应case,可扩展性极强
内容的提问来源于stack exchange,提问作者user9261559
相关产品推荐
相关产品推荐

