Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将JSONDecoder与继承/协议一起使用?_Ios_Json_Swift_Parsing_Codable - Fatal编程技术网

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

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

假设我有一个JSON中混合在一起的
员工
雇主
数组。两者都是从
个人继承的。在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答案。请考虑扩展您的答案。