Ios 如何将JSONDecoder与继承/协议一起使用?
假设我有一个JSON中混合在一起的Ios 如何将JSONDecoder与继承/协议一起使用?,ios,json,swift,parsing,codable,Ios,Json,Swift,Parsing,Codable,假设我有一个JSON中混合在一起的员工和雇主数组。两者都是从个人继承的。在JSONDecoder中处理它的正确方法是什么?类似的东西不起作用,因为我们无法将其转换回子类: let decoder = JSONDecoder() let persons = try! decoder.decode([Person].self, for: jsonData) 还有一点:我们可以在这里使用协议而不是超类吗 下面是我的示例JSON的样子: [ { "id": 1, "type": "em
员工
和雇主
数组。两者都是从个人继承的。在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转换为数据
值
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
}
}
正如您所看到的,employeeName
和employeeName
是可选项,因此此结构将能够保存JSON的每个元素(Employers
和Employee
)
人及其子类
假设你有一个像这样的类人
class Person {
let id: Int
let name:String
init(id:Int, name:String) {
self.id = id
self.name = name
}
}
您需要创建Employee
和employer
这样的子类
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)
}
}
请注意,员工
有一个可失败的初始值设定项,该初始值设定项将尝试创建员工
启动响应元素
。与雇主相同
让我们解码!
do{
let elements=try JSONDecoder().decode([ResponseElement].self,from:data)
让employees=elements.filter{$0.type==.employee}.flatMap(employee.init)
让employers=elements.filter{$0.type==.employer}.flatMap(employer.init)
打印(员工数)
打印(雇主计数)
}抓住{
印刷品("发生了一些不好的事情我刚刚找到了一个解决这个问题的好方法。嘿,Luca,谢谢你的解决方案。它肯定会起作用,但ResponseElement似乎对其他模型类太了解了。只有2个模型不是一个问题,但是有5-10个模型,每个模型有5-10个字段将导致一个样板代码,我想我在Github上找到了一个有趣的解决方案。请您好@ CopaPrimeste,请注意只包含一个链接的StAcExcel答案。请考虑扩展您的答案。