Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift中处理JSON解析时出错_Ios_Json_Swift_Swift2_Alamofire - Fatal编程技术网

Ios 在Swift中处理JSON解析时出错

Ios 在Swift中处理JSON解析时出错,ios,json,swift,swift2,alamofire,Ios,Json,Swift,Swift2,Alamofire,我正在使用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 positio

我正在使用
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未在隐式生成的super.init调用中初始化


但同时,用
0
值初始化
self.id
是错误的,对我没有任何帮助。

你可以使用??要提供如下默认值:

self.id = (representation.valueForKeyPath("id") as? Int) ?? 0
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
    }
}
但同时,使用值0初始化self.id是错误的,对我没有任何帮助

如果为
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
        }

        ...
更新

你在评论中说:


但我始终需要用户对象的id

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

let id = representation.valueForKeyPath("id") as! Int 
并在前面保证该值将存在


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

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


虽然它有一点学习曲线,但我更喜欢使用它进行JSON解析。一旦掌握了窍门,JSON解析就几乎是防弹的了。更好的是,它很容易与Alamofire集成,特别是今天发布的版本3。

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

self.id = (representation.valueForKeyPath("id") as? Int) ?? 0
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
    }
}

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

不过,我始终需要用户对象的id。如果我没有通过用户类提供错误,有没有一种方法可以抛出一个错误,或者在用户类中这样做是一种不好的做法?如果你必须有这个
id
,那么所有这些都是没有意义的,你只需要做
let id=representation.valueForKeyPath(“id”)as!Int
并在前面保证此值将存在。因为如果你的对象需要一个ID,那么如果这个值不存在,如果你不想要一个默认值,你无论如何也不能初始化。是的,我想这就是我要做的。我只是不希望应用程序崩溃,以防后端出现故障,并且由于任何原因没有向我提供id