Сбой свойств подкласса после сериализации JSON - PullRequest
0 голосов
/ 30 июня 2018

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

Вот класс:

import UIKit

class Patient: Person {
    var approved: Bool
    var doctorId: Int

    private enum CodingKeys: String, CodingKey {
        case approved
        case doctorId
    }

    init(id: String, name: String, lastName: String, phoneNumber: String, email: String, imageURL:URL, approved:Bool, doctorId:Int) {
        self.approved = approved
        self.doctorId = doctorId
        super.init(id: id, firstName: name, lastName: lastName, imageURL: imageURL)
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.approved  = try values.decode(Bool.self, forKey: .approved)
        self.doctorId = try values.decode(Int.self, forKey: .doctorId)
        try super.init(from: decoder)
    }

    var description: String {
        return "\(type(of: self)) - (\(self.firstName), \(self.lastName))" //superclass properties 
    }
}

struct PatientsList : Codable {
    let patients: [Patient]
}

Класс человека:

class Person: Codable {
    let firstName: String
    let lastName: String
    let imageURL: URL?
    let id: String

    private enum CodingKeys: String, CodingKey {
        case firstName
        case lastName
        case imageURL = "profileImgPath"
        case id = "_id"
    }

    init(id: String, firstName: String, lastName: String, imageURL:URL) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
        self.imageURL = imageURL
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try values.decode(String.self, forKey: .id)
        self.firstName = try values.decode(String.self, forKey: .firstName)
        self.lastName = try values.decode(String.self, forKey: .lastName)
        self.imageURL = try values.decodeIfPresent(URL.self, forKey: .imageURL)
    }
}

Вот как я выполняю сериализацию:

do {
                    let jsonData = try JSONSerialization.data(withJSONObject: JSON, options: [])
                    let decoder = JSONDecoder()
                    let patientList = try! decoder.decode(PatientsList.self, from: jsonData)
                    completionBlock(.success(patientList.patients))
                } catch {
                    print(error.localizedDescription)
                }

Вот // в консоли: po (Patient.approved) печатает false // в консоли: выражение dump (пациент)

▿ iHeal.Patient # 0 ▿ супер: iHeal.Person

firstName: "Sarah"

lastName: "Connor"

imageURL: nil

id: "5b367491052aaca6489e4805"

Дата рождения: "1980-06-10T00: 00: 00.000Z"

утверждено: false

doctorId: 12

print(patient.approved) //crash
print(patient.doctorId) // if I comment out previous line, this one crashes

Тема 1: EXC_BAD_ACCESS (код = 1, адрес = 0x200000002)

Еще одна странная вещь, которую я могу упомянуть: описание не вызывается у пациента

print(patient) // prints plain: <Patient: 0x608000141c30>

Json:

{
    "patients": [
        {
            "approved": false,
            "_id": "5b367491052aaca6489e4805",
            "birthDate": "1980-06-10T00:00:00.000Z",
            "doctorId": 12,
            "firstName": "Sarah",
            "lastName": "Connor"
        },
        {
            "approved": false,
            "drains": [],
            "_id": "5b3674e5052aaca6489e66b3",
            "__v": 0,
            "birthDate": "1980-06-10T00:00:00.000Z",
            "doctorId": 12,
            "firstName": "Sarah",
            "lastName": "Connor"
        }
    ]
}

Ответы [ 4 ]

0 голосов
/ 02 июля 2018

Дубликат: Сбой при доступе к свойствам объекта после декодирования из JSON

Удалено Codable соответствие из базового класса, т. Е. Person, но вы все равно можете декодировать членов базового класса, оставив метод init с докодером для вызова из дочерних классов. Дочерние классы теперь будут соответствовать Codable.

0 голосов
/ 30 июня 2018

Вы можете попробовать с помощью условия let, чтобы предотвратить падение приложения, используя следующий код:

if let isApproved = patient.approved {
    print(isApproved)
}

Этот код проверяет нулевое условие для свойства approved, проверяет, не является ли свойство нулевым, затем присваивает значение параметру isApproved, иначе условие исчезнет и код не будет выполнен внутри if block.

Это будет лучшим решением для предотвращения сбоев.

0 голосов
/ 01 июля 2018

Вы должны опубликовать свой JSON и как вы его анализируете. Минимальный пример как в

import Cocoa

let jsonData = """
{
    "doctorId": 12345,
    "approved": false
}
""".data(using: .utf8)!

struct Patient : Codable {
    var approved: Bool
    var doctorId: Int
}

do {
    let patient = try JSONDecoder().decode(Patient.self, from:jsonData)
    print(patient)
} catch {
    print(error)
}

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

Обновление

К сожалению, воспроизвести вашу ошибку по-прежнему нелегко. Я пытался

import Cocoa

let jsonData = """
{
    "patients": [
        {
            "approved": false,
            "drains": [],
            "_id": "5b367491052aaca6489e4805",
            "user": {
                "_id": "5b36747d28c1c608808274ce",
                "email": "17@iheal.com"
            },
            "__v": 0,
            "birthDate": "1980-06-10T00:00:00.000Z",
            "doctorId": 12,
            "firstName": "Sarah",
            "lastName": "Connor",
            "phoneNum": "123"
        },
        {
            "approved": false,
            "drains": [],
            "_id": "5b3674e5052aaca6489e66b3",
            "user": {
                "_id": "5b3674e428c1c608808274cf",
                "email": "18@iheal.com"
            },
            "__v": 0,
            "birthDate": "1980-06-10T00:00:00.000Z",
            "doctorId": 12,
            "firstName": "Sarah",
            "lastName": "Connor",
            "phoneNum": "123"
        }
    ]
}
""".data(using: .utf8)!

struct Patient : Codable {
    var approved: Bool
    var doctorId: Int
}

struct PatientList: Codable{
    let patients: [Patient]
}

do {
    let patients = try JSONDecoder().decode(PatientList.self, from:jsonData)
    print(patients)
} catch {
    print(error)
}

но с этим по-прежнему нет никаких проблем. Из того, что я вижу, мне нужно было бы угадать , как выглядит ваш Person -класс, но, скорее всего, это будет Codable. Честно говоря, у меня есть опыт наследования Codable типов, но ваш подход не выглядит необоснованным. Этот является , однако трудно судить, не является ли ваш класс Person частью вашего вопроса (и не является ли ваш JSON-анализ в его текущей форме). Боюсь, вам придется опубликовать эти вещи, чтобы получить значимый ответ.

0 голосов
/ 30 июня 2018

Я думаю, что у меня была похожая проблема, на самом деле это ноль, но когда вы печатаете ее в консоли, она возвращает false. Попробуйте добавить точку останова до print(patient.approved) и наберите в консоли expression patient.approved = false и посмотрите, не произойдет ли это (после того, как вы продолжите с этой точки торможения). Если нет, то вы знаете, в чем проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...