解码子类时忽略超类属性
Posted
技术标签:
【中文标题】解码子类时忽略超类属性【英文标题】:Ignoring superclass property while decoding subclass 【发布时间】:2017-10-17 00:10:34 【问题描述】:我正在尝试创建继承的数据模型,以便使用 JSONDecoder
解析它。
class FirstClass : Codable
let firstClassProperty: Int
final let arrayOfInts: [Int]
class SecondClass : FirstClass
let secondClassProperty1: Int
let secondClassProperty2: Int
private enum CodingKeys : String, CodingKey
case secondClassProperty1, secondClassProperty2
required init(from decoder: Decoder) throws
let container = try decoder.container(keyedBy: CodingKeys.self)
secondClassProperty1 = try container.decode(Int.self, forKey: .secondClassProperty1)
secondClassProperty2 = try container.decode(Int.self, forKey: .secondClassProperty2)
try super.init(from: decoder)
我将此 JSON 用于FirstClass
:
"firstClassProperty": 123,
"arrayOfInts": [
123
]
这是SecondClass
:
"firstClassProperty": ,
"secondClassProperty1": ,
"secondClassProperty2":
如果在这种情况下关键字 final
不起作用,我如何才能摆脱子类中的 arrayOfInts
而让它出现在超类中?
这里是Playground。感谢您的回答!
【问题讨论】:
如果不是总是需要arrayOfInts
,为什么它会出现在你的基类中?
这里似乎不需要层次结构。
【参考方案1】:
一个快速的技巧是将其声明为可选。例如:
class FirstClas: Codable
let firstClassProperty: Int
final let arrayOfInts: [Int]?
这将自动解决缺少的arrayOfInts
。
手动解决方案。另一种解决方案是自己实现Decodable
协议——就像你在SecondClass
中所做的那样——并使用decodeIfPresent
解码arrayOfInts
(否则使用默认值)。
超类解码。顺便说一句,将Decoder
转发给超类的推荐方法是使用superDecoder()
方法:
...
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)
【讨论】:
@LeoDabus 我自己是struct junkie,但是,如果没有来自good solitude3的更多信息,我不能像你说的那样直接杀死他的课程,哈哈;)他可能需要这种能力一个更大的应用程序,具有一整套未知的设计约束...... @LeoDabus 不是真的。正如我在回答中使用的那样,一个特定的superDecoder()
API 向我表明,Apple 明确地将其设计为供 classes 使用。这里和那里可能有一些缺失的部分,但我的意图似乎很清楚......
@LeoDabus ...苹果实际上提供了complete, detailed example in WWDC 2017 :-)
我不会这么说的。这个问题主要集中在忽略超类属性(而不是关于继承作为另一个问题的全面讨论)。 OP 真的无法通过仅查看另一个更大的问题来破解解决方案,恕我直言......【参考方案2】:
你可以这样使用:
class FirstClass : Codable
let firstClassProperty: Int
final let arrayOfInts: [Int]?
required init(from decoder: Decoder) throws
let container = try decoder.container(keyedBy: CodingKeys.self)
firstClassProperty = try container.decode(Int.self, forKey: .firstClassProperty)
arrayOfInts = try container.decodeIfPresent([Int].self, forKey: .arrayOfInts)
【讨论】:
如果属性已经被标记为可选,我认为自动生成的代码在这里可能就足够了——顺便说一下,应该和你手动生成的非常相似写;)以上是关于解码子类时忽略超类属性的主要内容,如果未能解决你的问题,请参考以下文章