Декодирование / кодирование массива смешанных объектов из данных JSON - PullRequest
0 голосов
/ 29 мая 2019

У меня проблемы с реализацией правильного способа синтаксического анализа входящих данных JSON в кодируемые объекты из-за массива, который содержит смешанные объекты, и я не могу понять, как проанализировать этот массив в массив с их соответствующими типы объектов.

Я попытался следовать предложению отсюда, так как оно кажется похожим, но безуспешно. Reddit ссылка на проверенное решение.

Я также прочитал эту статью и те, на которые она ссылается. Ссылка на статью.

Но я просто очень озадачен тем, что именно мне нужно реализовать из-за моей неопытности с 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!)

И, наконец, мое проверенное решение, которое я не могу заставить работать, потому что я не знаю, как точно написать кодировщик. Я пытаюсь следовать аналогичному примеру, объяснил здесь

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

1 Ответ

0 голосов
/ 29 мая 2019

Одна вещь, которую я заметил, что jsonResponse ключа объяснения содержит массив словаря, но оба словаря должны иметь одинаковый набор ключей и разные пары значений.Но это не так.поэтому вы не сможете расшифровать его, пока он не станет таким же, я надеюсь, он вам поможет.

...