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
相关产品推荐
相关产品推荐

