从JSON数据解码/编码混合对象数组

时间:2019-05-29 11:50:39

标签: json swift codable

由于数组混合了对象,我无法实现将传入的JSON数据解析为可编码对象的正确方法,并且无法弄清楚如何使用以下方法将该数组解析为数组它们各自的对象类型。

我尝试遵循这里的建议,因为它似乎很相似,但是没有运气。 Reddit link to tried solution.

我也对本文及其引用的文章进行了红色标记。 Article link.

但是由于我对swift缺乏经验并且是新来的人,我对应该正确执行的事情感到非常困惑。

使用伪数据,我传入的JSON数据看起来像this.

我的Swift模型还包含几个嵌套结构,但是这些都没有问题,因此我只会粘贴相关的位。但基本上看起来像这样:

struct Message: Codable {
    let messageID: Int
    let appVersion: String
    let certaintyFactor: Int
    let comments: String?
    let defaultPriority: String
    let explanation: [Explanation]
    let name: String
    let patient: [PatientInfo]
    let risk: String
    let rule: Rule
    let urgency: String

struct Explanation: Codable {
    let id, name: String
    let content: Resource

    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case content
    }
}

“资源”可能是对象的模型

struct Patient: Codable{
    let id: String
    let text: Text
    let identifier: [Identifier]
    let active: Bool
    let name: [Name]
    let telecom: [Identifier]
    let gender, birthDate: String
    let deceasedBoolean: Bool
    let address: [Address]
    let maritalStatus: MaritalStatus
    let multipleBirthBoolean: Bool
    let contact: [Contact]
    let communication: [Communication]
    let managingOrganization: ManagingOrganization

}

struct Address: Codable {
    let use: String
    let line: [String]
    let city, postalCode, country: String
}

struct Communication: Codable {
    let language: MaritalStatus
    let preferred: Bool
}

struct MaritalStatus: Codable {
    let coding: [MaritalStatusCoding]
    let text: String
}

struct MaritalStatusCoding: Codable {
    let system: String
    let code, display: String
}

struct Contact: Codable {
    let relationship: [Relationship]
    let name: Name
    let telecom: [Identifier]
}

struct Name: Codable {
    let use, family: String
    let given: [String]
    let suffix: [String]?
}

struct Relationship: Codable {
    let coding: [RelationshipCoding]
}

struct RelationshipCoding: Codable {
    let system: String
    let code: String
}

struct ManagingOrganization: Codable {
    let reference, display: String
}
struct MedicationRequest: Codable {
    let resourceType, id: String
    let text: Text
    let contained: [Contained]
    let identifier: [Identifier]
    let status, intent: String
    let medicationReference: MedicationReference
    let subject, context: Context
    let authoredOn: String
    let requester: Requester
    let dosageInstruction: [DosageInstruction]
    let dispenseRequest: DispenseRequest
    let substitution: Substitution
}

struct Contained: Codable {
    let resourceType, id: String
    let code: Reason
}

struct Reason: Codable {
    let coding: [Coding]
}

struct Coding: Codable {
    let system: String
    let code, display: String
    let type: String?
}

struct Context: Codable {
    let reference, display: String
}

struct DispenseRequest: Codable {
    let validityPeriod: Period
    let numberOfRepeatsAllowed: Int
    let quantity, expectedSupplyDuration: ExpectedSupplyDuration
}

struct ExpectedSupplyDuration: Codable {
    let value: Int
    let unit: String
    let system: String
    let code: String
}

struct Period: Codable {
    let start, end: String
}

struct DosageInstruction: Codable {
    let sequence: Int
    let text: String
    let additionalInstruction: [Reason]
    let timing: Timing
    let asNeededCodeableConcept, route: Reason
    let doseQuantity, maxDosePerAdministration: ExpectedSupplyDuration
}

struct Timing: Codable {
    let timingRepeat: Repeat

    enum CodingKeys: String, CodingKey {
        case timingRepeat = "repeat"
    }
}

struct Repeat: Codable {
    let boundsPeriod: Period
    let frequency, period, periodMax: Int
    let periodUnit: String
}

struct MedicationReference: Codable {
    let reference: String
}

struct Requester: Codable {
    let agent: Context
    let onBehalfOf: MedicationReference
}

struct Substitution: Codable {
    let allowed: Bool
    let reason: Reason
}

解析部分

let jsonData = try? JSON(parseJSON: rowData).rawData()
let message = try? JSONDecoder().decode(Message.self, from: jsonData!)

最后是我无法通过测试的解决方案,因为我不知道如何精确地编写编码器。

import Foundation

enum AnyResource : Codable {
    case patient(Patient)
    case medicationRequest(MedicationRequest)

    private enum CodingKeys :String, CodingKey {
        case patient
        case medicationRequest
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            self = .patient(try container.decode(Patient.self, forKey: .patient))
        } catch DecodingError.keyNotFound {
            do {
                self = .medicationRequest(try container.decode(MedicationRequest.self, forKey: .medicationRequest))
            }
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        /// I think I'm supposed to use a .nestedcontainer here? with a similar switch statement?

    }
}

1 个答案:

答案 0 :(得分:0)

有一件事,我注意到解释键的jsonResponse拥有一个字典数组,但是,两个字典应该具有相同的键集和不同的值对。但事实并非如此。因此您无法解码它,直到我希望它能对您有所帮助为止。