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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:21:46