如何让String类型的Codable枚举兼容Objective-C并保留JSON解析能力?
实现方案
要同时满足Objective-C 兼容和原JSON字符串解析兼容性,可以按以下步骤调整:
1. 修改枚举基础配置
将枚举的原始类型从String改为Int,添加@objc关键字使其能被Objective-C识别,同时显式指定每个成员的Int原始值(Objective-C要求必须明确赋值)。
2. 保留字符串映射关系
新增私有属性和初始化方法,维护原字符串值与枚举成员的对应关系,确保JSON解析时能正确转换。
3. 自定义Codable实现
重写解码、编码方法,让解码逻辑同时支持原JSON的字符串格式和Objective-C的Int格式,编码时仍输出原字符串值以保持兼容性。
完整代码实现
@objc public enum MyEnum: Int, Codable, Hashable, Sendable { case one = 0 case two = 1 // 映射原JSON中的字符串值 private var originalString: String { switch self { case .one: return "ONE" case .two: return "TWO" } } // 从原字符串值初始化枚举 private init?(fromOriginalString string: String) { switch string { case "ONE": self = .one case "TWO": self = .two default: return nil } } // 自定义解码逻辑:兼容String/Int输入,解析失败默认返回.one public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // 优先解析原JSON的String格式 if let rawString = try? container.decode(String.self) { self = MyEnum(fromOriginalString: rawString) ?? .one return } // 兼容Objective-C的Int格式解析 if let rawInt = try? container.decode(Int.self) { self = MyEnum(rawValue: rawInt) ?? .one return } // 非预期格式时使用默认值 self = .one } // 自定义编码逻辑:输出原字符串值,保持与旧版本JSON格式一致 public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(originalString) } }
关键说明
- Objective-C兼容:枚举会以
MyEnumOne、MyEnumTwo的形式暴露给Objective-C代码,可直接调用。 - JSON兼容性:解码时优先处理字符串输入,完全匹配原有解析逻辑;编码输出原字符串,保证序列化后的JSON格式不变。
- 容错逻辑:保留了原代码中解析失败返回
.one的行为,同时新增Int格式的容错处理。
内容的提问来源于stack exchange,提问作者Tometoyou
相关产品推荐
相关产品推荐

