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

Decodable结构体能否存储未解码值?扩展Course结构体需新增结构体吗?

关于Swift Decodable结构体的两个问题解答

1. Decodable结构体中是否可以存在未解码的值?

可以。

默认情况下,当JSON中存在CodingKeys枚举未定义的字段时,Swift的Decodable会自动忽略这些未匹配的键,不会触发解码错误。

如果需要主动保留这些未解码的额外数据,可以通过自定义解码初始化方法实现。比如给结构体添加存储额外字段的属性,再在init(from decoder: Decoder)中解析所有未被CodingKeys匹配的键值对:

struct Course: Decodable, Identifiable {
    var name: String?
    var courseCode: String
    var id: Int
    var image_download_url: String?
    var term: Term?
    // 存储未解码的额外字段
    var extraData: [String: Any]?

    private enum CodingKeys: String, CodingKey {
        case id, name, image_download_url, term, courseCode = "course_code"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 解码已定义字段
        name = try container.decodeIfPresent(String.self, forKey: .name)
        courseCode = try container.decode(String.self, forKey: .courseCode)
        id = try container.decode(Int.self, forKey: .id)
        image_download_url = try container.decodeIfPresent(String.self, forKey: .image_download_url)
        term = try container.decodeIfPresent(Term.self, forKey: .term)

        // 解析未匹配的额外字段
        let allKeys = container.allKeys
        var extraData = [String: Any]()
        for key in allKeys {
            if !CodingKeys.allCases.contains(where: { $0.rawValue == key.stringValue }) {
                if let value = try? container.decode(String.self, forKey: key as! CodingKeys) {
                    extraData[key.stringValue] = value
                } else if let value = try? container.decode(Int.self, forKey: key as! CodingKeys) {
                    extraData[key.stringValue] = value
                }
                // 可根据需求扩展更多类型解析
            }
        }
        self.extraData = extraData.isEmpty ? nil : extraData
    }
}

2. 希望该结构体还能存储bgColor值,是否需要定义新结构体?

不需要,直接在原Course结构体中添加bgColor属性即可,分两种场景处理:

场景一:bgColor不是从JSON解码而来

直接声明属性并设置默认值,或在初始化结构体时手动赋值,无需修改CodingKeys:

struct Course: Decodable, Identifiable {
    var name: String?
    var courseCode: String
    var id: Int
    var image_download_url: String?
    var term: Term?
    // 新增本地存储的bgColor属性
    var bgColor: UIColor = .white

    private enum CodingKeys: String, CodingKey {
        case id, name, image_download_url, term, courseCode = "course_code"
    }
}

// 使用示例
let course = try JSONDecoder().decode(Course.self, from: jsonData)
course.bgColor = .blue

场景二:bgColor是JSON中的字段

只需将bgColor加入CodingKeys(若JSON键名与属性名一致,无需重命名;不一致则指定rawValue):

struct Course: Decodable, Identifiable {
    var name: String?
    var courseCode: String
    var id: Int
    var image_download_url: String?
    var term: Term?
    // 从JSON解码的bgColor属性
    var bgColor: String? // 假设JSON中是字符串格式的颜色值,比如"#FFFFFF"

    private enum CodingKeys: String, CodingKey {
        case id, name, image_download_url, term, courseCode = "course_code", bgColor
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:17:03