如何将JSONDecoder与继承/协议一起使用?

时间:2017-11-11 12:42:04

标签: ios json swift parsing codable

假设我在JSON中将employeesemployers的单个数组混合在一起。两者都继承自Person。在JSONDecoder中处理它的正确方法是什么?因为我们无法将其强制转换为子类,所以我们无法工作:

let decoder = JSONDecoder()
let persons = try! decoder.decode([Person].self, for: jsonData)

另一点:我们可以在这里使用协议而不是超类吗?

这就是我的示例JSON的样子:

[
{
    "id": 1,
    "type": "employee",
    "employee_name": "xy"
},
{
    "id": 2,
    "type": "employer",
    "employer_name": "xz"
}
]

2 个答案:

答案 0 :(得分:0)

首先让我们在Data

中转换你的json
let data = """
[
    {
        "id": 1,
        "type": "employee",
        "employee_name": "xy"
    },
    {
        "id": 2,
        "type": "employer",
        "employer_name": "xz"
    }
]
""".data(using: .utf8)!
  

重要提示:替换“!”使用更安全的展开方法

模型

现在我们需要一个模型值来加工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
    }
}
  

正如您所看到的,employeeNameemployerName选项,因此此结构将能够保存JSON的每个元素(Employers和{{ 1}})。

人及其子类

假设你有一个类Employee这样的

Person

您需要像这些

一样创建class Person { let id: Int let name:String init(id:Int, name:String) { self.id = id self.name = name } } Employee子类
Empolyer
  

请注意,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) } } 有一个可用的初始值设定项,会尝试创建Employee起始Employee。与ResponseElement相同。

让我们解码!

Employer

答案 1 :(得分:0)

我刚刚找到了一个很好的solution来解决这个问题。