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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:21:05