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

Swift中如何将JSON字典数组映射至Enum枚举类型

解决JSON字典数组映射到Swift枚举的问题

要将返回的JSON字典数组映射到你定义的Role枚举,需要自定义Codable的实现逻辑——默认的枚举Codable解析仅处理单个值(如直接的Int或String),而你的JSON是包含id和name的对象结构,需要适配这种结构。

步骤1:修改Role枚举,实现自定义Codable

enum Role: Int, Codable, Identifiable {
    case student = 1
    case faculty = 2
    
    var id: Int { rawValue }
    
    // 对应JSON中的name字段,用于匹配验证
    var name: String {
        switch self {
        case .student: return "Student"
        case .faculty: return "Faculty"
        }
    }
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 取出JSON中的id值
        let rawId = try container.decode(Int.self, forKey: .id)
        // 取出name值并验证是否与枚举对应
        let jsonName = try container.decode(String.self, forKey: .name)
        
        guard let role = Role(rawValue: rawId), role.name == jsonName else {
            throw DecodingError.dataCorruptedError(
                forKey: .name,
                in: container,
                debugDescription: "角色ID与名称不匹配,或ID无效"
            )
        }
        
        self = role
    }
    
    // 可选:如果需要将枚举转回JSON结构,实现编码逻辑
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(rawValue, forKey: .id)
        try container.encode(name, forKey: .name)
    }
    
    // 定义JSON对应的键名
    private enum CodingKeys: String, CodingKey {
        case id, name
    }
}

步骤2:解码JSON数组

直接使用JSONDecoder解码为[Role]类型即可,单个Role的解析逻辑已在枚举中实现:

// 示例JSON数据(实际场景替换为服务返回的data)
let jsonString = """
[
    {
        "id": 1,
        "name": "Student"
    },
    {
        "id": 2,
        "name": "Faculty"
    }
]
"""

guard let jsonData = jsonString.data(using: .utf8) else {
    print("JSON格式错误")
    return
}

do {
    let roles = try JSONDecoder().decode([Role].self, from: jsonData)
    print("解码结果:\(roles)") // 输出 [Role.student, Role.faculty]
} catch {
    print("解码失败:\(error.localizedDescription)")
}

简化版(不验证name字段)

如果不需要校验JSON中的name与枚举的对应关系,可以简化解码逻辑:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let rawId = try container.decode(Int.self, forKey: .id)
    
    guard let role = Role(rawValue: rawId) else {
        throw DecodingError.dataCorruptedError(
            forKey: .id,
            in: container,
            debugDescription: "无效的角色ID:\(rawId)"
        )
    }
    
    self = role
}

内容的提问来源于stack exchange,提问作者user19037628

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:21:24