JSON序列化后子类属性崩溃
我有一个最奇怪的问题。执行JSON序列化并创建对象后,代码在尝试访问子类的任何属性时崩溃。当我尝试访问对象超类的属性时,它们被正确地打印出来 下面是课堂:JSON序列化后子类属性崩溃,json,swift,serialization,Json,Swift,Serialization,我有一个最奇怪的问题。执行JSON序列化并创建对象后,代码在尝试访问子类的任何属性时崩溃。当我尝试访问对象超类的属性时,它们被正确地打印出来 下面是课堂: import UIKit class Patient: Person { var approved: Bool var doctorId: Int private enum CodingKeys: String, CodingKey { case approved case doct
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(患者批准)打印错误
//控制台中:表达式转储(患者)
▿ 我死了,病人#0▿ 超级:我真的很好
firstName: "Sarah"
lastName: "Connor"
imageURL: nil
id: "5b367491052aaca6489e4805"
出生日期:“1980-06-10T00:00:00.000Z”
批准:错误
医生:12
线程1:EXC\u坏访问(代码=1,地址=0x20000002)
我还可以提到另一件奇怪的事:病人身上不需要描述
print(patient) // prints plain: <Patient: 0x608000141c30>
我想我也有类似的问题,它实际上是零,但当你在控制台中打印它时,它返回false。尝试在打印(patient.approved)之前添加一个断点,然后在控制台中键入
expression patient.approved=false
,查看该断点是否崩溃(从该制动点继续后)。如果没有,那么您就知道问题出在哪里了。我想我也有类似的问题,它实际上是零,但当您在控制台中打印它时,它返回false。尝试在打印(patient.approved)之前添加一个断点,然后在控制台中键入expression patient.approved=false
,查看该断点是否崩溃(从该制动点继续后)。如果没有,则您知道问题所在。您可以尝试使用If-let条件,通过使用以下代码防止应用程序崩溃:
if let isApproved = patient.approved {
print(isApproved)
}
此代码将检查approved
属性的nil条件,它将检查属性是否为非nil,然后将值分配给isApproved
参数,否则条件将消失,代码不会在内执行,如果阻塞
这将是防止崩溃问题的更好解决方案。您可以尝试使用if-let条件,通过使用以下代码防止应用程序崩溃:
if let isApproved = patient.approved {
print(isApproved)
}
此代码将检查approved
属性的nil条件,它将检查属性是否为非nil,然后将值分配给isApproved
参数,否则条件将消失,代码不会在内执行,如果阻塞
这将是防止崩溃问题的更好解决方案。您应该发布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
类型的经验,但您的方法看起来并不不合理。然而,如果您的Person
类不是您的问题的一部分(您当前形式的JSON解析也是如此),则很难判断这一点。我担心您必须发布这些内容才能得到有意义的响应。您应该发布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
类型的经验,但您的方法看起来并不不合理。然而,如果您的Person
类不是您的问题的一部分(您当前形式的JSON解析也是如此),则很难判断这一点。恐怕您必须发布这些内容才能得到有意义的回复。重复:
已从基类(即Person)中删除Codable
一致性,但您仍然可以通过保持从子类调用带有docoder的init方法来解码基类成员。子类现在将符合Codable。重复:
已从基类(即Person)中删除Codable
一致性,但您仍然可以通过保持从子类调用带有docoder的init方法来解码基类成员。子类现在将符合Codable。您可以共享json
响应吗?你是如何初始化这个对象的?@Luda,什么是person类?嗨@Kamran,我已经更新了这个问题(我最初认为有点不同)嗨@SagarChauhan,我已经更新了这个问题(我最初认为有点不同)@Luda,看起来是同一个问题。你能试一下吗。你能分享一下json
响应吗?你是如何初始化这个对象的?@Luda,什么是person类?嗨@Kamran,我已经更新了这个问题(我最初认为有点不同)嗨@SagarChauhan,我已经更新了这个问题(我最初认为有点不同)@Luda,看起来是同一个问题。你能试试吗。approved
不是一个可选的
变量,所以这段代码会产生一个编译器错误。我得到:条件绑定的初始值设定项必须具有可选类型,而不是'Bool'在问题中添加了JSON。hi@Sagar Chauhan,我已经更新了这个问题(与我最初认为的有点不同)approved
不是一个optional
变量,因此此代码将创建一个编译器错误。我得到:条件绑定的初始值设定项必须具有可选类型,而不是'Bool'在questionHi@Sagar Chauhan中添加了JSON,我更新了问题(与