从 JSON 解码后访问对象属性时崩溃

Posted

技术标签:

【中文标题】从 JSON 解码后访问对象属性时崩溃【英文标题】:Crash when accessing Object properties after decoding from JSON 【发布时间】:2018-06-23 19:31:36 【问题描述】:

我已将 JSON 值解码为对象。该对象看起来像预期的那样,但是当我尝试访问它的属性时。

let jsonData = try JSONSerialization.data(withJSONObject: JSON, options: [])
let decoder = JSONDecoder()
let doctor = try! decoder.decode(Doctor.self, from: jsonData)
let txt = "\(doctor.title). \(doctor.firstName) \(doctor.lastName)" // Runtime crash: (Thread 1: EXC_BAD_ACCESS (code=1, address=0x40))

运行时崩溃:(线程 1:EXC_BAD_ACCESS(代码=1,地址=0x40))

班级人员:

import UIKit

class Person: Codable 
    let firstName: String
    let lastName: String
    let imageURL: URL

    private enum CodingKeys: String, CodingKey 
        case firstName
        case lastName
        case imageURL = "profileImgPath"
    

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

班主任:

import UIKit

class Doctor: Person 
    var title: String


    private enum CodingKeys: String, CodingKey 
        case title
    

    init(firstName: String, lastName: String, imageURL:URL, title: String) 
        self.title = title
        super.init(firstName: firstName, lastName: lastName, imageURL: imageURL)
    

    required init(from decoder: Decoder) throws 

        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.title = try values.decode(String.self, forKey: .title)
        try super.init(from: decoder)
    


【问题讨论】:

firstNamelastNameDoctor 中的计算属性吗?你能显示Doctor 类吗? 我猜如果您不使用try! 并实际捕获异常,您可能会获得更多详细信息,您是否在Doctor 上实现了Codable DoctorPerson 的子类吗? @Kamran 我已经更新了问题 我认为它需要在 Person 类中使用 init(from decoder:) 方法。编辑:我看到卡姆兰在他们的回答中做到了。 【参考方案1】:

当我尝试你的代码时,它产生了同样的错误,经过调查,我发现这是Swift 4.1 中的一个问题。您可以在下面查看,

https://bugs.swift.org/browse/SR-7090

目前可能的解决方案可能是如下所示的轻微重新排列,

从基类中删除Codable 一致性,即Person,但您仍然可以通过将init 方法与docoder 一起从子类中调用来解码基类成员。子类现在将符合Codable

class Person 
    let firstName: String
    let lastName: String
    let imageURL: URL

    private enum CodingKeys: String, CodingKey 
        case firstName
        case lastName
        case imageURL = "profileImgPath"
    

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

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


class Doctor: Person, Codable 
    var title: String


    private enum CodingKeys: String, CodingKey 
        case title
    

    init(firstName: String, lastName: String, imageURL:URL, title: String) 
        self.title = title
        super.init(firstName: firstName, lastName: lastName, imageURL: imageURL)
    

    required override init(from decoder: Decoder) throws 

        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.title = try values.decode(String.self, forKey: .title)
        try super.init(from: decoder)
      

现在,如果您有以下 json,它将按预期工作。

let json = """

  "title":"SomeTitle",
  "firstName": "SomeFirstName",
  "lastName": "SomeLastName",
  "profileImgPath": "urlPath"

""".data(using: .utf8)!

let decoder = JSONDecoder()
let doctor = try! decoder.decode(Doctor.self, from: json)
print(doctor.firstName)
print(doctor.lastName)
print(doctor.title)

【讨论】:

很高兴它有帮助。 基类没有来自解码器的初始化。编译器应该已经捕捉到并尖叫我承认......但这也是合乎逻辑的......

以上是关于从 JSON 解码后访问对象属性时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:访问 NSManagedObject 属性时应用程序崩溃

如何使用 Alamofire 和 Swift Decode 从 JSON 解码和访问 Double

在 migratePersistentStore: 到 OS X 10.9 Mavericks 上的另一个 URL 后访问 NSManagedObject 属性时崩溃

无法读取未定义的属性“URL” - 访问 JSON 对象

无法访问 JSON 对象属性 [重复]

在反应渲染方法中访问对象属性