使用 SwiftyJSON 解析 JSON 响应而不会崩溃

Posted

技术标签:

【中文标题】使用 SwiftyJSON 解析 JSON 响应而不会崩溃【英文标题】:Parse JSON response with SwiftyJSON without crash 【发布时间】:2016-07-07 10:26:41 【问题描述】:

我的 ios 应用正在从服务器获取 JSON 响应

let myURL = NSURL(string: SERVER_URL);
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = ""
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
    
        data, response, error in

        if error != nil 
            print("error=\(error)")
            return
        

        dispatch_async(dispatch_get_main_queue(),

            var json = JSON(data: data!)
            let someInt = json["someInt"].int
            let message = json["message"].stringValue

有时服务器已关闭或 JSON 中可能存在错误,因此不会有此类值(消息、someInt),我想在不导致应用崩溃的情况下处理它 - 我该怎么办?

【问题讨论】:

【参考方案1】:

使用 SwiftyJSON,非可选的 getter 以 Value 结尾,而可选的 getter 则不是。

所以要测试该值是否在这里,您可以使用可选绑定 if let:

if let someInt = json["someInt"].int,
    message = json["message"].string 
        // someInt and message are available here
 else 
    // someInt and message are not available

或者guard:

guard let someInt = json["someInt"].int,
    message = json["message"].string else 
        // error, someInt and message are not available
        return

// someInt and message are available here

【讨论】:

不是 SwiftyJSON,而是如何处理错误的一个很好的例子:***.com/a/31808605/2227743【参考方案2】:

很简单,您可能已经知道了,您可以使用以下方法保护您的代码:

if  let someInt = json["someInt"].int 
    // do whatever you want with someInt

if let message = json["message"].string 
    // do whatever you want with message


试试这个方法:

request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) 
                data, response, error in
                if let data = data,
                   jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
                    where error == nil 
                        var json = JSON(data: data!)
                        // use some protection as explained before..
                 else 
                    print("error=\(error!.localizedDescription)")
                
            
task.resume()

【讨论】:

我认为问题出在之前的某个地方(var json = JSON(data: data!) NSString(data:_, encoding:_) 接受非可选值,你应该在之前验证data(因为 NSURLSession 返回一个可选数据)。那么你不能假设 responseString 不为空。这可能会导致崩溃【参考方案3】:

让我也发布我的答案 =)

首先你可以为失败的 JSON 初始化器实现小的扩展:

extension JSON 
    init?(_ data: NSData?) 
        if let data = data 
            self.init(data: data)
         else 
            return nil
        
    

您可以将它放在全局范围内并导入SwiftyJSON,而忘记在JSON 中使用之前强制解包数据。如果您使用它们,可以为其他数据类型编写相同的失败初始化程序。它只是为了将来更短且可读的代码。对于许多路由或在某些情况下,例如当您从 json 中等待某些单个字段时,此扩展可以使您的代码看起来非常简单易读:

guard let singleMessage = JSON(data: data)?["message"].string else return

然后你需要以你需要的方式检查 nil (实际上在之前的答案中解释过)。可能您正在搜索完全有效的数据,所以使用 if-let 链:

let myURL = NSURL(string: SERVER_URL);
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = ""
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
    
        data, response, error in

        if error != nil 
            print("error=\(error)")
            return
        

        dispatch_async(dispatch_get_main_queue()) 

            if let json = JSON(data: data),
                   someInt = json["someInt"].int,
                   message = json["message"].string,
                   // ...
            
                // all data here, do what you want

             else 
                print("error=\(error)")
                return
            
        
    

【讨论】:

【参考方案4】:

最好是使用 try catch 来处理

request.HTTPBody = postdata.dataUsingEncoding(NSUTF8StringEncoding)
    let task  = NSURLSession.sharedSession().dataTaskWithRequest(request)
    
        (data, response, error) in
        dispatch_async(dispatch_get_main_queue(), 
        var jsondata: AnyObject?
        do
        
            let jsondata = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
            print(jsondata)
            // your code here
        
        catch
        
                print("Some Error Found")
        
    )

    

    task.resume()

如果您遇到任何错误,您将在控制台中收到一条消息,从而防止应用程序崩溃

【讨论】:

是但不是:OP 没有使用 NSJSONSerialization,他们使用的是 SwiftyJSON。 谢谢,但我真的需要 SwiftyJSON 的解决方案!

以上是关于使用 SwiftyJSON 解析 JSON 响应而不会崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 SwiftyJSON 解析 JSON 响应

我应该如何使用 Alamofire 和 SwiftyJSON 解析来自 API 的 JSON 响应?

如何使用 SwiftyJson 解析 json 响应。以下是我的代码和回复

使用 SwiftyJSON 处理 JSON 响应

使用 SwiftyJSON 将 JSON 解析为结构

使用 SwiftyJSON(和 Alamofire)解析 JSON 值