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

标签 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

    enum CodingKeys: CodingKey {
        case id
        case text
        case identifier
        case active
        case name
        case telecom
        case gender
        case birthDate
        case deceasedBoolean
        case address
        case maritalStatus
        case multipleBirthBoolean
        case contact
        case communication
        case 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

    enum CodingKeys: String, CodingKey {
        case resourceType
        case id
        case text
        case contained
        case identifier
        case status
        case intent
        case medicationReference
        case subject
        case context
        case authoredOn
        case requester
        case dosageInstruction
        case dispenseRequest
        case 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
}

//// MARK: - Text
struct Text: Codable {
    let status, div: String

    enum CodingKeys: String, CodingKey {
        case status,div
    }
}

// MARK: - Identifier
struct Identifier: Codable {
    let use: String
    let system: String
    let value: String
}

解析部分

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

最后,我经过测试的解决方案无法正常工作,因为我不知道如何准确编写编码器。 我正在尝试遵循类似的示例,解释为 here

enum Resource{
    case patient(Patient)
    case medicationRequest(MedicationRequest)
}

extension Resource :Codable {
    enum CodingKeys: CodingKey {
        case patient
        case medicationRequest
    }

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

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        switch self {
        case .patient(let value):
            try container.encode(value, forKey: .patient)
        case .medicationRequest(let value):
            try container.encode(value, forKey: .medicationRequest)
        }
    }
}

最佳答案

我注意到解释键的 jsonResponse 包含一个字典数组,但是两个字典应该具有相同的键集和不同的值对。但事实并非如此。所以在它相同之前你无法解码它我希望它对你有帮助。

关于json - 从 JSON 数据解码/编码混合对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56359959/

相关文章:

swift - 如何处理等待嵌套 URLSession 完成的情况

ios - Swift 4 使用 CodableFirebase 和自定义类处理来自 Firestore 的 nil 值

c# - JSON.NET 序列化 JObject 而忽略空属性

java - 尝试将 JSON(使用 GSON)读入一个具有另一个对象作为字段的对象。

ios - 当我将 UITableViewCell 作为 AnyObject 传递时,我的应用程序崩溃了吗?到另一个功能

arrays - 如果单元素解码失败,Swift JSONDecode 解码数组将失败

ios - 如何用Codable解析键值json?

java - 使用 Java 通过 TCP 发送 JSON 对象

javascript 错误 [jsonFlickrApi 未定义]

swift - 检查选择器中的数据 swift