继承Codable时子类属性无法赋值问题求助(附示例代码)
解决Swift Codable子类属性无法被编码/解码的问题
这个问题我之前也碰到过,核心原因是Swift的Codable协议在继承场景下的自动合成规则容易被忽略:当子类继承自一个已经遵循Codable的父类时,编译器不会自动为子类合成包含自身属性的Codable实现逻辑。所以你对Secondary实例进行编解码时,只会执行父类Primary的Codable逻辑,完全跳过了子类的b属性,导致它始终保持默认值0。
解决方案一:显式让子类遵循Codable协议
最简单的修复方式就是给Secondary显式添加Codable协议声明,这样编译器会自动为子类合成包含自身属性b的编解码代码,同时会自动调用父类的相关方法:
class Primary : Codable { var a: Int = 0 } class Secondary : Primary, Codable { var b: Int = 0 }
解决方案二:手动实现Codable方法(自定义场景)
如果需要对编解码逻辑进行自定义(比如处理可选值、重命名字段等),可以手动实现init(from:)和encode(to:)方法,确保同时处理父类和子类的属性:
class Primary : Codable { var a: Int = 0 } class Secondary : Primary { var b: Int = 0 // 定义子类的编码键 enum CodingKeys: String, CodingKey { case b } // 必须实现required的解码初始化方法 required init(from decoder: Decoder) throws { // 先解码子类自己的属性 let container = try decoder.container(keyedBy: CodingKeys.self) b = try container.decode(Int.self, forKey: .b) // 再调用父类的解码方法 try super.init(from: decoder) } // 重写编码方法 override func encode(to encoder: Encoder) throws { // 先编码子类自己的属性 var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(b, forKey: .b) // 再调用父类的编码方法 try super.encode(to: encoder) } }
验证测试
你可以在Playground中添加以下代码验证修复效果:
// 创建子类实例并赋值 let secondary = Secondary() secondary.a = 5 secondary.b = 10 // 编码为JSON let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try encoder.encode(secondary) print(String(data: data, encoding: .utf8)!) // 解码回实例 let decoder = JSONDecoder() let decodedSecondary = try decoder.decode(Secondary.self, from: data) print("解码后a的值:\(decodedSecondary.a),解码后b的值:\(decodedSecondary.b)")
执行后你会看到JSON中同时包含a和b的键值对,解码后的实例两个属性都能正确获取到设置的值。
内容的提问来源于stack exchange,提问作者Adrian_H
相关产品推荐
相关产品推荐

