【问题标题】:Error handling parsing JSON in Swift在 Swift 中解析 JSON 的错误处理
【发布时间】:2015-10-10 22:18:31
【问题描述】:

我正在使用Alamofire 并将返回的 JSON 解析为如下所示的对象:

final class User: NSObject, ResponseObjectSerializable {
    var id: Int
    var facebookUID: String?
    var email: String
    var firstName: String
    var lastName: String
    var phone: String?
    var position: String?
    var timeCreated: CVDate

    init?(response: NSHTTPURLResponse, var representation: AnyObject) {
        if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
            representation = dataRepresentation
        }

        if let id = representation.valueForKeyPath("id") as? Int {
            self.id = id
        } else {
            self.id = 0
        }

        if let facebookUID = representation.valueForKeyPath("facebook_UID") as? String {
            self.facebookUID = facebookUID
        }

        if let email = representation.valueForKeyPath("email") as? String {
            self.email = email
        } else {
            self.email = ""
        }

        if let firstName = representation.valueForKeyPath("first_name") as? String {
            self.firstName = firstName
        } else {
            self.firstName = ""
        }

        if let lastName = representation.valueForKeyPath("last_name") as? String {
            self.lastName = lastName
        } else {
            self.lastName = ""
        }

        if let phone = representation.valueForKeyPath("phone") as? String {
            self.phone = phone
        }

        if let position = representation.valueForKeyPath("position_name") as? String {
            self.position = position
        }

        if let timeCreated = representation.valueForKeyPath("time_created") as? String {
            let formatter = NSDateFormatter()
            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
            if let date = formatter.dateFromString(timeCreated) {
                self.timeCreated = CVDate(date: date)
            } else {
                self.timeCreated = CVDate(date: NSDate())
            }
        } else {
            self.timeCreated = CVDate(date: NSDate())
        }
    }
}

我的问题是,这种风格是解码 JSON 和设置非可选实例变量的最佳方式吗?例如,在这个语句中:

if let id = representation.valueForKeyPath("id") as? Int {
    self.id = id
}

编译器要求我添加一个 else 子句并将 id 设置为其他值,否则 xCode 会抛出错误:self.id is not initialized at implicitly generated super.init call

但与此同时,将 self.id 初始化为 0 的值是错误的,对我毫无帮助。

【问题讨论】:

    标签: ios json swift swift2 alamofire


    【解决方案1】:

    但与此同时,将 self.id 的值初始化为 0 是错误的,对我一点帮助也没有。

    如果self.id 的默认值感觉不对,那么您应该将此属性设为可选。这样您就不必添加 else 子句:

    final class User: NSObject, ResponseObjectSerializable {
        var id: Int?
        var facebookUID: String?
        var email: String
        var firstName: String
        var lastName: String
        var phone: String?
        var position: String?
        var timeCreated: CVDate
    
        init?(response: NSHTTPURLResponse, var representation: AnyObject) {
            if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
                representation = dataRepresentation
            }
    
            if let id = representation.valueForKeyPath("id") as? Int {
                self.id = id
            }
    
            ...
    

    更新

    你在cmets中说:

    不过,我总是需要有一个用户对象的 id。

    如果你必须拥有这个 id 属性,那么问题就没有实际意义了,你只需要这样做

    let id = representation.valueForKeyPath("id") as! Int 
    

    并保证更早这个值会存在。

    因为如果你的对象需要一个ID,那么你无论如何都不能初始化它如果这个值不存在并且如果你不想要默认值。

    【讨论】:

    • 我总是需要一个用户对象的 id。如果没有通过 User 类为我提供错误,或者在里面这样做是一种不好的做法,有没有一种方法可以引发错误?
    • 好吧,如果你必须拥有这个id,那么这一切都没有实际意义,你只需要做let id = representation.valueForKeyPath("id") as! Int 并保证更早这个值会存在。因为如果你的对象需要一个ID,那么如果这个值不存在并且如果你不想要一个默认值,你无论如何都不能初始化。
    • 是的,我想这就是我必须要做的。我只是不希望应用程序崩溃,以防后端发生一些故障,并且无论出于何种原因我都没有获得 id
    【解决方案2】:

    你可以使用 ??提供这样的默认值:

    self.id = (representation.valueForKeyPath("id") as? Int) ?? 0
    

    【讨论】:

      【解决方案3】:

      虽然 ResponseObjectSerializable 代码是 Alamofire 项目的一个很好的示例,但使用具有实际错误状态的专用 JSON 解析库确实是一个更好的主意。这比使用可选项来表示错误状态或必须为每个字段提供默认值以防响应未正确形成要好得多。

      虽然它有一些学习曲线,但我更喜欢使用Argo 进行 JSON 解析。一旦你掌握了它的窍门,它就会使 JSON 解析几乎是万无一失的。更好的是,它很容易与 Alamofire 集成,尤其是今天发布的第 3 版。

      【讨论】:

        【解决方案4】:

        为了解决您对没有 ID 成为错误条件的担忧,您可以使用可失败的初始化程序。我在最近的一个项目中这样做了。看起来像这样:

        let id: Int!
        
        init? (inputJson: NSDictionary) {
        
            if let id = inputJson["id"] as? Int {
                self.id = id
            } else {
                // if we are initing from JSON, there MUST be an id
                id = nil
                cry(inputJson) // this logs the error
                return nil
            }
        }
        

        当然,这意味着您的代码需要接受整个对象的初始化可能会失败..

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-07-27
          • 2012-12-13
          • 2012-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-24
          • 2021-04-05
          相关资源
          最近更新 更多