如何在Codable结构体中添加自定义临时属性?
为Codable结构体添加自定义临时属性的几种方案
针对你的VideoAlbum结构体,要添加不需要参与JSON编码/解码的临时属性,其实有几种简单且符合Swift Codable设计的方案,下面逐一说明:
方案一:添加计算属性(最简单)
计算属性不属于存储属性,Codable自动合成的编码/解码方法不会处理它们,所以直接添加即可,适合那些基于已有属性计算得出的临时值:
struct VideoAlbum: Codable { let id, image: String? let video, mediaType: JSONNull? let type, deleted, createdOn: String? let modifiedOn: JSONNull? // 自定义临时计算属性 - 比如标记是否被选中 var isSelected: Bool { // 可以根据其他属性动态计算,比如判断id是否存在 return id != nil } enum CodingKeys: String, CodingKey { case id, image, video case mediaType = "media_type" case type, deleted case createdOn = "created_on" case modifiedOn = "modified_on" } }
方案二:添加存储属性(可选/带默认值)
如果你的临时属性需要存储值(不是计算出来的),只要把它声明为可选类型或者带有默认值,并且不加入CodingKeys中,Codable自动合成的方法就会忽略它:
struct VideoAlbum: Codable { let id, image: String? let video, mediaType: JSONNull? let type, deleted, createdOn: String? let modifiedOn: JSONNull? // 可选类型的临时存储属性 - 比如本地标记的标签 var tempTag: String? // 带默认值的临时存储属性 - 比如标记是否收藏 var isFavorite: Bool = false enum CodingKeys: String, CodingKey { case id, image, video case mediaType = "media_type" case type, deleted case createdOn = "created_on" case modifiedOn = "modified_on" } }
这种方式下,tempTag和isFavorite完全是本地使用的属性,不会被编码到JSON,解码时也不会从JSON读取,完全不影响原有Codable逻辑。
方案三:必须初始化的存储属性(手动实现解码)
如果你的临时属性是非可选且没有默认值的,就需要手动实现init(from:)方法,在解码时给这个属性赋值:
struct VideoAlbum: Codable { let id, image: String? let video, mediaType: JSONNull? let type, deleted, createdOn: String? let modifiedOn: JSONNull? // 必须初始化的临时存储属性 let tempID: Int enum CodingKeys: String, CodingKey { case id, image, video case mediaType = "media_type" case type, deleted case createdOn = "created_on" case modifiedOn = "modified_on" } // 手动实现解码初始化 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 解码原有属性 id = try container.decodeIfPresent(String.self, forKey: .id) image = try container.decodeIfPresent(String.self, forKey: .image) video = try container.decodeIfPresent(JSONNull.self, forKey: .video) mediaType = try container.decodeIfPresent(JSONNull.self, forKey: .mediaType) type = try container.decodeIfPresent(String.self, forKey: .type) deleted = try container.decodeIfPresent(String.self, forKey: .deleted) createdOn = try container.decodeIfPresent(String.self, forKey: .createdOn) modifiedOn = try container.decodeIfPresent(JSONNull.self, forKey: .modifiedOn) // 给临时属性赋值,这里可以根据业务需求设置,比如生成随机ID tempID = Int.random(in: 1...1000) } // 编码方法可以用自动合成的,因为临时属性不在CodingKeys中,不会被编码 }
补充:完善你的JSONNull类
你的JSONNull类代码不完整,这里给出完整实现,确保它能正确处理JSON中的null值:
class JSONNull: Codable { public init() {} public required init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if !container.decodeNil() { throw DecodingError.dataCorruptedError( in: container, debugDescription: "Expected null but found non-null value." ) } } public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encodeNil() } }
内容的提问来源于stack exchange,提问作者Prashant Tukadiya
相关产品推荐
相关产品推荐

