First of all lets transform your json in a Data
value
let data = """
[
{
"id": 1,
"type": "employee",
"employee_name": "xy"
},
{
"id": 2,
"type": "employer",
"employer_name": "xz"
}
]
""".data(using: .utf8)!
Important: Replace the "!" with a safer unwrapping method
Model
Now we need a model value to mach the element in your JSON
struct ResponseElement:Codable {
let id: Int
let type: Type
let employeeName: String?
let employerName: String?
enum CodingKeys: String, CodingKey {
case id, type, employeeName = "employee_name", employerName = "employer_name"
}
enum `Type`:String, Codable {
case employee, employer
}
}
As you can see employeeName
and employerName
are optionals, so this struct will be able to hold every element of your JSON (Employers
and Employee
).
Person and its subclasses
Assuming you have a class Person
like this
class Person {
let id: Int
let name:String
init(id:Int, name:String) {
self.id = id
self.name = name
}
}
You'll need to create the Employee
and Empolyer
subclasses like these
class Employee:Person {
init?(responseElement:ResponseElement) {
guard let name = responseElement.employeeName, responseElement.type == .employee else { return nil }
super.init(id: responseElement.id, name: name)
}
}
class Employer:Person {
init?(responseElement:ResponseElement) {
guard let name = responseElement.employerName, responseElement.type == .employer else { return nil }
super.init(id: responseElement.id, name: name)
}
}
Please note that an Employee
has a failable initializer that will try to create an Employee
starting ResponseElement
. Same for Employer
.
Lets decode!
do {
let elements = try JSONDecoder().decode([ResponseElement].self, from: data)
let employees = elements.filter { $0.type == .employee }.flatMap(Employee.init)
let employers = elements.filter { $0.type == .employer }.flatMap(Employer.init)
print(employees.count)
print(employers.count)
} catch {
print("Something bad has happened :\(error)")
}