繁体   English   中英

如何在继承/协议中使用JSONDecoder?

[英]How to use JSONDecoder with inheritance / protocols?

假设我有一个由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"
}
]

首先让我们将您的json转换为Data

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的每个元素( EmployersEmployee )。

人及其子类

假设你有一班这样的Person

class Person {
    let id: Int
    let name:String

    init(id:Int, name:String) {
        self.id = id
        self.name = name
    }
}

您需要创建像这样的EmployeeEmpolyer子类

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有一个失败的初始化程序,它将尝试创建一个从ResponseElement开始的Employee Employer

让我们解码!

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)")
}

我刚刚找到了解决这个问题的好方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM