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

Swift中Codable枚举解码异常:PlatformModel的slug为何为nil?

解码JSON时PlatformModel的slug为nil的原因及解决方法

问题背景

我为slug属性创建了PlatformIconType枚举用于按钮图标显示,但解码JSON时无报错,却导致PlatformModel中的slug值为nil,请问原因是什么?

相关代码

Model:

struct PlatformsModel: Codable {
    let platform: PlatformModel?
    let requirements: RequirementsModel?
}

struct PlatformModel: Codable {
    let id: Int?
    let name: String?
    let slug: PlatformIconType?
}

Enum:

enum PlatformIconType: String, Codable {
    case pc = "pc"
    case ps3 = "playstation3"
    case ps4 = "playstation4"
    case ps5 = "playstation5"
    case xbox360 = "xbox360"
    case xboxSX = "xbox-series-x"
    case xboxOne = "xbox-one"
    
    var icon: UIImage {
        switch self {
        case .pc:
            return UIImage(systemName: "desktopcomputer")!
        case .ps3:
            return UIImage(systemName: "playstation.logo")!
        case .ps4:
            return UIImage(systemName: "playstation.logo")!
        case .ps5:
            return UIImage(systemName: "playstation.logo")!
        case .xbox360:
            return UIImage(systemName: "xbox.logo")!
        case .xboxSX:
            return UIImage(systemName: "xbox.logo")!
        case .xboxOne:
            return UIImage(systemName: "xbox.logo")!
        }
    }
}

JSON示例:

"platforms": [
            {
                "platform": {
                    "id": 4,
                    "name": "PC",
                    "slug": "pc"
                }
            },
            {
                "platform": {
                    "id": 186,
                    "name": "Xbox Series S/X",
                    "slug": "xbox-series-x"
                }
            },
            {
                "platform": {
                    "id": 18,
                    "name": "PlayStation 4",
                    "slug": "playstation4"
                }
            },
            {
                "platform": {
                    "id": 16,
                    "name": "PlayStation 3",
                    "slug": "playstation3"
                }
            },
            {
                "platform": {
                    "id": 14,
                    "name": "Xbox 360",
                    "slug": "xbox360"
                }
            },
            {
                "platform": {
                    "id": 1,
                    "name": "Xbox One",
                    "slug": "xbox-one"
                }
            },
            {
                "platform": {
                    "id": 187,
                    "name": "PlayStation 5",
                    "slug": "playstation5"
                }
            }
        ]

核心原因

出现这种情况的关键在于可选类型枚举的默认解码行为:当你把slug声明为PlatformIconType?(可选枚举类型)时,如果JSON中的字符串无法匹配枚举的任何rawValue,Swift的Codable解码器不会抛出错误,而是直接将该可选属性设为nil。

具体可能的触发场景:

  • 枚举未覆盖所有返回的slug值:如果API返回的JSON中存在你枚举里没定义的slug(比如某个小众平台),解码时就会把slug设为nil。
  • 大小写不匹配:Swift的字符串枚举是大小写敏感的,如果API返回的slug和你枚举的rawValue大小写不一致(比如JSON返回"PC"而你枚举是case pc = "pc"),也会导致匹配失败,slug变为nil。
  • 隐性解码异常:虽然你提供的示例JSON里的slug都能匹配枚举,但实际请求中可能存在返回格式异常的情况(比如某个slug字段为空字符串),同样会触发可选属性设为nil的逻辑。

解决方法

1. 强制解码报错,快速定位问题

把slug的可选类型去掉,改为非可选:

struct PlatformModel: Codable {
    let id: Int?
    let name: String?
    let slug: PlatformIconType // 去掉问号
}

这样一旦出现无法匹配的slug,解码器会直接抛出错误,你可以通过捕获错误信息快速找到不匹配的slug值。

2. 添加未知case,兼容所有情况

给枚举新增一个unknowncase,并自定义解码逻辑,把无法匹配的slug都归为这个case,避免出现nil:

enum PlatformIconType: String, Codable {
    case pc = "pc"
    case ps3 = "playstation3"
    case ps4 = "playstation4"
    case ps5 = "playstation5"
    case xbox360 = "xbox360"
    case xboxSX = "xbox-series-x"
    case xboxOne = "xbox-one"
    case unknown

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let rawValue = try container.decode(String.self)
        self = PlatformIconType(rawValue: rawValue) ?? .unknown
    }
}

之后你可以在icon属性的switch里给.unknown设置一个默认图标,保证界面正常显示。

3. 补全所有可能的枚举case

对照API文档或实际返回的所有slug值,把枚举里缺失的case补充完整,从根源上避免匹配失败。

内容的提问来源于stack exchange,提问作者Ufuk Köşker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:15:11