Swift 4.0 Codable-解码子类,继承的类,异构数组

Swift 4.0引入了一个非常有用的API。 如果您一直在关注Swift项目和该版本中使用该语言的新功能,则可能已经听说过。 在使用某些REST API时,我遇到了一些问题,因此想在这里记录它们,以防其他人遇到相同的情况。

如果您熟悉Codable ,则可以跳过本节,如果不是,这就是文档页面上Apple汇总的方式:

使您的数据类型可编码和可解码,以与JSON等外部表示兼容。

关于如何使用此新API,已经有很多不错的文章。 这些是最好的,我建议阅读它们作为切入点:

编码和解码自定义类型

Swift 4 JSON解析终极指南

Swift 4 Decodable:超越基础📦

异构数组是指您拥有一个包含多个不同对象的JSON片段。 在我的情况下,这些对象是基类Drink子类。每个子类具有不同的属性,需要序列化。

首先,需要定义模型,符合可Decodable协议。 从基类开始,然后是子类。

这是基类,定义了与之关联的所有属性。 这没有什么复杂的,因此不需要编写自定义代码,它只使用标准API。

Beer还具有alcohol_content属性,因此我们需要添加它。 此类需要在基类之前进行初始化。 我们需要编写自己的自定义init方法。 您可以在第11行看到,我们将相同的解码器对象传递给超类,以便它可以对基类属性进行解码。

这就是我们将json转换为内存的方式。 这里没有什么复杂的,但是我们现在需要定义Drinks对象。 该对象包含一个异构数组,因此我们需要自己实现Decodable协议。

第2行显示我们将Drink对象的数组作为属性添加到此类。

接下来,我们创建一个枚举DrinksKey ,该枚举用于解码包含饮料数组的字典。

我们还定义了一个枚举DrinkTypeKey ,它用于序列化数组中每个对象的类型字段。

最后的枚举DrinkTypes与指定所有可能的饮料类型。

使用所有指定的枚举,我们可以进行序列化。

第19行:获取饮料字典- container

第20行:获取饮料数组— drinkArrayForType

第23行:复制drinksArray数组— drinksArray这是必需的,因为我们要迭代drinkArrayForType 。这样做时,我们将无法获取数组中每个元素的解码器对象。 请参阅下面的摘要。

第24行:迭代drinkArrayForType容器

第25行:获取当前的饮料容器

第26行:解码type属性

现在,我们可以使用此解码属性来标识要解码的类。 但是,我们必须使用复制的drinksArray对象进行解码,因为drinksArrayForType的迭代器已移至下一个对象。 中提琴!

最后一步是我可以获得Decodable API进行出价的唯一方法。 据我所知,没有办法从UnkeyedDecodingContainerKeyedDecodingContainer获取解码器。这似乎是对API的限制,但我肯定有充分的理由使其无法使用。 仅在这种解码用例中公开这种依赖性似乎有些奇怪。

如果您有其他想法,请告诉我,可能值得进一步考虑,并为Swift API本身添加改进建议。 毕竟,这只是该API的第一次迭代,其可能的开发人员可能会错过此用例。


最初于 2017 年9月18日 发布在 medium.com 上。