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

为SwiftUI类添加@Observable后出现解码警告及JSON加载失败问题

解决@Observable与Codable冲突导致的JSON解码问题

问题根源

给遵循Codable的类添加@Observable修饰符后,Swift为Observable生成的合成逻辑会干扰Codable的自动解码合成。编译器误判属性存在不可覆盖的初始值,进而触发警告并导致JSON加载失败。

解决方案:手动实现Codable方法

放弃依赖自动合成的Codable实现,手动编写init(from decoder:)和encode(to:)方法,明确控制每个属性的解码/编码流程,规避Observable合成逻辑的干扰。

示例:Address类修改

@Observable
class Address: Codable {
    var street: String
    var city: String
    var zipCode: String
    
    // 定义编码/解码键
    enum CodingKeys: String, CodingKey {
        case street, city, zipCode
    }
    
    // 手动实现解码初始化器
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        street = try container.decode(String.self, forKey: .street)
        city = try container.decode(String.self, forKey: .city)
        zipCode = try container.decode(String.self, forKey: .zipCode)
    }
    
    // 手动实现编码方法
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(street, forKey: .street)
        try container.encode(city, forKey: .city)
        try container.encode(zipCode, forKey: .zipCode)
    }
}

嵌套类处理(如Programmer类)

如果程序员模型嵌套了Address这类Observable类,同样需要手动实现Codable方法:

@Observable
class Programmer: Codable {
    var name: String
    var address: Address
    
    enum CodingKeys: String, CodingKey {
        case name, address
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        // 手动解码嵌套的Address对象
        address = try container.decode(Address.self, forKey: .address)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encode(address, forKey: .address)
    }
}

额外检查项

  • 确认JSON文件的键名与CodingKeys完全一致,避免拼写错误
  • 验证JSON加载逻辑,确保文件路径正确、数据读取正常:
func loadProgrammers() -> [Programmer] {
    guard let url = Bundle.main.url(forResource: "programmers", withExtension: "json"),
          let data = try? Data(contentsOf: url),
          let programmers = try? JSONDecoder().decode([Programmer].self, from: data) else {
        return []
    }
    return programmers
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:06:23