您的数组包含有限的、可枚举的种类的异构对象;听起来像是 Swift 枚举的完美用例。它不适合多态,因为从概念上讲,这些“东西”不一定是同一类。他们只是碰巧被标记了。
这样看:你有一系列带有标签的东西,有些是这种类型,有些是完全不同的类型,还有一些......有时你甚至不认识标签。 Swift 枚举是体现这一想法的完美工具。
所以你有一堆共享标签属性但在其他方面彼此完全不同的结构:
struct Foo: Decodable {
let tag: String
let fooValue: Int
}
struct Bar: Decodable {
let tag: String
let barValue: Int
}
struct Baz: Decodable {
let tag: String
let bazValue: Int
}
并且您的数组可以包含上述类型或未知类型的任何实例。所以你有枚举TagggedThing
(或者更好的名字)。
enum TagggedThing {
case foo(Foo)
case bar(Bar)
case baz(Baz)
case unknown
}
用 Swift 术语来说,你的数组属于类型[TagggedThing]
。所以你符合TagggedThing
键入至Decodable
像这样:
extension TagggedThing: Decodable {
private enum CodingKeys: String, CodingKey {
case tag
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let tag = try container.decode(String.self, forKey: .tag)
let singleValueContainer = try decoder.singleValueContainer()
switch tag {
case "foo":
// if it's not a Foo, throw and blame the server guy
self = .foo(try singleValueContainer.decode(Foo.self))
case "bar":
self = .bar(try singleValueContainer.decode(Bar.self))
case "baz":
self = .baz(try singleValueContainer.decode(Baz.self))
default:
// this tag is unknown, or known but we don't care
self = .unknown
}
}
}
现在您可以解码以下 JSON:
let json: Data! = """
[
{"tag": "foo", "fooValue": 1},
{"tag": "bar", "barValue": 2},
{"tag": "baz", "bazValue": 3}
]
""".data(using: .utf8)
像这样:
let taggedThings = try? JSONDecoder().decode([TagggedThing].self, from: json)