This is a solution with nested containers. With the given (simplified but valid) JSON string
let jsonString = """
{
"zones": [
{
"name": "zoneA",
"blocks": [
{"name": "Foo"}
]
},
{
"name": "zoneB",
"blocks": [
{"street":"Broadway", "city":"New York"}
]
},
{
"name": "zoneC",
"blocks": [
{"email": "[email protected]"}
]
},
{
"name": "zoneD",
"blocks": [
{"phone": "555-01234"}
]
}
]
}
"""
and the corresponding element structs
struct ElementA : Decodable { let name: String }
struct ElementB : Decodable { let street, city: String }
struct ElementC : Decodable { let email: String }
struct ElementD : Decodable { let phone: String }
first decode the zones as nestedUnkeyedContainer then iterate the array and decode first the name key and depending on name the elements.
Side note: This way requires to declare the element arrays as variables.
struct Root : Decodable {
var elementsA = [ElementA]()
var elementsB = [ElementB]()
var elementsC = [ElementC]()
var elementsD = [ElementD]()
enum Zone: String, Decodable { case zoneA, zoneB, zoneC, zoneD }
private enum CodingKeys: String, CodingKey { case zones }
private enum ZoneCodingKeys: String, CodingKey { case name, blocks }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
var zonesContainer = try container.nestedUnkeyedContainer(forKey: .zones)
while !zonesContainer.isAtEnd {
let item = try zonesContainer.nestedContainer(keyedBy: ZoneCodingKeys.self)
let zone = try item.decode(Zone.self, forKey: .name)
switch zone {
case .zoneA: elementsA = try item.decode([ElementA].self, forKey: .blocks)
case .zoneB: elementsB = try item.decode([ElementB].self, forKey: .blocks)
case .zoneC: elementsC = try item.decode([ElementC].self, forKey: .blocks)
case .zoneD: elementsD = try item.decode([ElementD].self, forKey: .blocks)
}
}
}
}
Decoding the stuff is straightforward
do {
let result = try JSONDecoder().decode(Root.self, from: Data(jsonString.utf8))
print(result)
} catch {
print(error)
}
ElementAfrom anElementB? I mean with "real difference" in what are they properties, etc.? Does thenameproperties is linked to the kind of elements?