【问题标题】:Parse JSON response with SwiftyJSON without crash使用 SwiftyJSON 解析 JSON 响应而不会崩溃
【发布时间】: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),我想在不导致应用崩溃的情况下处理它 - 我该怎么办?

【问题讨论】:

    标签: ios json swift swifty-json


    【解决方案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
    

    【讨论】:

    【解决方案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 的解决方案!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多