Кодируемый для класса с наследованием - PullRequest
1 голос
/ 04 октября 2019

Я пытаюсь следующий код, но выдает исключение

import Foundation

class SomeBaseClass: Codable {
    let someInt: Int?
    let someString: String?

    init(someInt: Int,someString:String) {
        self.someInt = someInt
        self.someString = someString
    }

    init(someBaseClass: SomeBaseClass) {
        self.someString = someBaseClass.someString
        self.someInt = someBaseClass.someInt
    }
}

class Person: SomeBaseClass {
    let firstName: String?
    let lastName: String?

    init(firstName: String,lastName:String,someBaseClass: SomeBaseClass) {
        self.firstName = firstName
        self.lastName = lastName

        super.init(someBaseClass: someBaseClass)
    }

    enum CodingKeys: String, CodingKey {
        case firstName,lastName
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        firstName = try container.decode(String.self, forKey: .firstName)
        lastName = try container.decode(String.self, forKey: .lastName)

        try super.init(from: container.superDecoder())
    }

}

let json = """
{
    "firstName":"John",
    "someInt":2

}
"""

let jsonData = json.data(using: .utf8)!

do {
    let personObject = try JSONDecoder().decode(Person.self, from: jsonData)
    dump(personObject)
} catch let error as NSError {
    print(error)
}

Сбой со следующей ошибкой

Ошибка домена = NSCocoaErrorDomain Code = 4865 "Нет связанных значенийс ключом CodingKeys (stringValue: "lastName", intValue: nil) ("lastName"). "UserInfo = {NSDebugDescription = Нет значения, связанного с ключом CodingKeys (stringValue: «lastName», intValue: nil) («lastName»)., NSCodingPath = ()}

Я знаю, lastName отсутствуетв JSON, и я пометил его как необязательный, но он не работает так, как он работает для структур

Есть ли простой способ сделать то же самое?

1 Ответ

2 голосов
/ 04 октября 2019

Вы должны использовать decodeIfPresent для дополнительных свойств

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

    try super.init(from: decoder)
}

Также обратите внимание на изменение в super, которое было необходимо, чтобы избежать другой ошибки. Вы также можете немного изменить свой улов с

} catch let error as NSError {
    print(error)
}

на просто

} catch {
    print(error)
}
...