swift - Swift Decodable 用于混合类型的列表或项目
问题描述
在我最近开发的几个应用程序中,我需要阅读混合类型项目的列表。“现实生活”情况的一个很好的例子是文章中的项目列表:有标题、副标题、正文、图像等。
我想出了这样的事情:
// Sample data:
//
// {
// items: [
// {
// "type": "a",
// "a": "This one is A"
// },
// {
// "type": "b",
// "b": "This one is B"
// }
// ]
// }
import Foundation
// MARK: - "Root" protocol for all decodable items
protocol Item: Decodable {}
// MARK: - Items
struct ItemA: Item { let a: String }
struct ItemB: Item { let b: String }
// MARK: - Extractor
/// Helper for extracting items
struct ItemExtractor: Decodable {
enum TypeKey: String, Decodable {
case a
case b
}
let item: Item
// MARK: - Decodable compliance
enum CodingKeys: String, CodingKey {
case type
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let type = try values.decode(TypeKey.self, forKey: .type)
let itemValues = try decoder.singleValueContainer()
// In particular, looking to eliminate this `switch`
switch type {
case .a:
item = try itemValues.decode(ItemA.self)
case .b:
item = try itemValues.decode(ItemB.self)
}
}
}
// MARK: - Container
/// Container of items
struct MyList: Decodable {
let items: [Item]
// MARK: - Decodable compliance
enum CodingKeys: String, CodingKey {
case items
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let extractors = try values.decode([ItemExtractor].self, forKey: .items)
items = extractors.map { $0.item }
}
}
- 数据文件中项目的类型用“类型”字段标记;
- ItemExtractor助手读取类型并根据其类型初始化项目;
- 然后从 ItemExtractor 数组中取出这些项目,并将其添加到 MyList 结构中的项目列表中。
现在的问题是:有没有一种方法可以概括此代码以避免 ItemExtractor 中的switch语句,如果有很多不同类型的项目,或者可能有完全不同的方法,这将特别有用?
期待更好的解决方案,–Baglan
解决方案
推荐阅读
- outlook - Outlook 显示 iCal 日期已更改,尽管它是同一日期
- spring-boot - ZooKeeper 最新值不会在不重新启动服务器的情况下重新加载
- keycloak - 密钥斗篷授权
- angular - Angular 7等待所有订阅
- c - 分段错误内存转储
- java - 在 actionlistener 中更改变量数据
- mysql - 如何让mysql查询更快
- jsp - 战争中的图像未显示在 JSP 上
- php - 在 Wamp Server Mysql 命令行中使用 Mysqldump 备份所有数据库时出现错误 1064(42000)
- azure-active-directory - Intune 公司门户应用和第 3 方 iOS 应用之间的“SSO”