【问题标题】:How to parse JSON in Swift using NSURLSession如何使用 NSURLSession 在 Swift 中解析 JSON
【发布时间】:2015-10-26 14:35:37
【问题描述】:

我正在尝试解析 JSON,但收到此错误:

没有更多上下文,表达式的类型是模棱两可的

我的代码是:

func jsonParser() {

    let urlPath = "http://headers.jsontest.com/"
    let endpoint = NSURL(string: urlPath)
    let request = NSMutableURLRequest(URL:endpoint!)

    let session = NSURLSession.sharedSession()
    NSURLSession.sharedSession().dataTaskWithRequest(request){ (data, response, error) throws -> Void in

        if error != nil {
            print("Get Error")
        }else{
            //var error:NSError?
            do {
                let json:AnyObject =  try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary

            print(json)

        } catch let error as NSError {
            // error handling
            print(error?.localizedDescription)
        }
        }
    }
    //task.resume()
}

在 Xcode 6.4 中不使用 try catch 可以正常工作,但在 Xcode 7 中不起作用。

【问题讨论】:

    标签: json swift


    【解决方案1】:

    不要为您的解码对象声明 AnyObject 类型,因为您希望它是 NSDictionary 并且您正在执行转换来执行此操作。

    此外,NSJSONSerialization 最好使用零选项而不是随机选项。

    在我的示例中,我还使用自定义错误类型来进行演示。

    请注意,如果您使用的是自定义错误类型,则还必须包含一个通用的 catch 才能详尽无遗(在本示例中,简单地向下转换为 NSError)。

    enum JSONError: String, ErrorType {
        case NoData = "ERROR: no data"
        case ConversionFailed = "ERROR: conversion from JSON failed"
    }
    
    func jsonParser() {
        let urlPath = "http://headers.jsontest.com/"
        guard let endpoint = NSURL(string: urlPath) else {
            print("Error creating endpoint")
            return
        }
        let request = NSMutableURLRequest(URL:endpoint)
        NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
            do {
                guard let data = data else {
                    throw JSONError.NoData
                }
                guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary else {
                    throw JSONError.ConversionFailed
                }
                print(json)
            } catch let error as JSONError {
                print(error.rawValue)
            } catch let error as NSError {
                print(error.debugDescription)
            }
       }.resume()
    }
    

    与 Swift 3.0.2 相同:

    enum JSONError: String, Error {
        case NoData = "ERROR: no data"
        case ConversionFailed = "ERROR: conversion from JSON failed"
    }
    
    func jsonParser() {
        let urlPath = "http://headers.jsontest.com/"
        guard let endpoint = URL(string: urlPath) else {
            print("Error creating endpoint")
            return
        }
        URLSession.shared.dataTask(with: endpoint) { (data, response, error) in
            do {
                guard let data = data else {
                    throw JSONError.NoData
                }
                guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary else {
                    throw JSONError.ConversionFailed
                }
                print(json)
            } catch let error as JSONError {
                print(error.rawValue)
            } catch let error as NSError {
                print(error.debugDescription)
            }
        }.resume()
    }
    

    【讨论】:

      【解决方案2】:

      Apple 在此声明。

      func dataTaskWithRequest(request: NSURLRequest, completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask
      

      修复它:

      NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
             // Your handle response here!
      }
      

      更新:

      func jsonParser() {
          let urlPath = "http://headers.jsontest.com/"
          let endpoint = NSURL(string: urlPath)
          let request = NSMutableURLRequest(URL:endpoint!)
      
          NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
              print(error)
          }.resume()
      }
      

      结果:

      可选(错误域=NSURLErrorDomain 代码=-1022 “无法加载资源,因为应用程序传输安全策略需要使用安全连接。” UserInfo={NSUnderlyingError=0x7f8873f148d0 {错误域=kCFErrorDomainCFNetwork 代码=-1022 "(null)"}, NSErrorFailingURLStringKey=http://headers.jsontest.com/, NSErrorFailingURLKey=http://headers.jsontest.com/, NSLocalizedDescription=无法加载资源,因为应用>传输安全策略要求使用安全连接。})

      希望这会有所帮助!

      【讨论】:

      • 我也用过这段代码,但出现错误“表达式类型不明确,没有更多上下文”。
      • 看看我的代码。删除代码中的 throws 。请!
      • 我会在 PlayGround 上测试它。稍等。
      • 更新代码在没有编译器错误的情况下工作,但是当我们在这个块中编写代码时 { let json:AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary print(json) } catch let error as NSError { // 错误处理 print(error?.localizedDescription) } .出现错误。
      • 稍后我会查看您的问题。现在,我很忙:p
      【解决方案3】:

      对于 Swift 4 Web 服务调用,使用 URLSession 的 Post 方法

       func WebseviceCall(){
              var request = URLRequest(url: URL(string: "YOUR_URL")!)
              request.httpMethod = "POST"
              let postString = "PARAMETERS"
              request.httpBody = postString.data(using: .utf8)
              request.setValue("application/json", forHTTPHeaderField: "Content-Type")
              request.setValue("application/json", forHTTPHeaderField: "Accept")
      
              let task = URLSession.shared.dataTask(with: request) { data, response, error in
      
                  guard let data = data, error == nil else {
                      print("error=\(error)")
                      return
                  }
      
                  if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                      print("statusCode should be 200, but is \(httpStatus.statusCode)")
                      print("response = \(response)")
                  }
      
                  do {
                      if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                          // Print out dictionary
                          print(convertedJsonIntoDict)
                     }
                  } catch let error as NSError {
                      print(error.localizedDescription)
                  }
              }
              task.resume()
          }
      

      【讨论】:

        【解决方案4】:

        这里是使用 NSUrlSession 解析 JSON 的最简单方法,

         let PARAMS = "{\"params1\":\"%@\",\"Params2\":\"%@\",\"params3\":\"%@\"}"
         let URL = "your url here"
        

        在提交按钮上写下这段代码,

        let urlStr = String(format: "%@",URL)
        let jsonString = String(format:PARAMS, params1value,params2value,params3value )
        // Encode your data here
        let jsonData = jsonString.data(using:.utf8)
        var request = URLRequest(url: URL(string: urlStr)!)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        //set your method type here 
        request.httpMethod = "POST"
        request.httpBody = jsonData
        let configuration = URLSessionConfiguration.default
        // create a session here
        let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
            let task = session.dataTask(with: request) {(data , response, error) in
                if(error != nil){
                    print("Error \(String(describing: error))")
                }
         else {
                    do {
                        let fetchedDataDictionary = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
                        print(fetchedDataDictionary!)
                        let message = fetchedDataDictionary?["response key here"] as! String
                        if message == "your response string" {
                            print(message)
        
                        }
                        else {
                             self.dataArray = (fetchedDataDictionary?["data"] as! NSArray)
                        }
                    }
                    catch let error as NSError {
                        print(error.debugDescription)
                    }
                }
            }
            task.resume()
        

        【讨论】:

          【解决方案5】:

          1) 将 ApiConnection 类添加到您的项目中.. 进口基金会 类 ApiConnection: NSObject {

          class func postDataWithRequest(_ dicData:NSDictionary, completionHandler:@escaping (_ response:NSDictionary?,_ status:Bool)->Void)
          {
              let URL=Foundation.URL(string: Constant.API_URL)
              let request=NSMutableURLRequest(url: URL!)
              request.httpMethod="POST"
              request.addValue(Constant.kApplicationJSON, forHTTPHeaderField:Constant.kContentType)
              let data=try? JSONSerialization .data(withJSONObject: dicData, options: JSONSerialization.WritingOptions.prettyPrinted)
              request.httpBody=data
          
              //let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC)*5))
              //dispatch_after(dispatchTime, dispatch_get_main_queue()) {
              let session = URLSession.shared.dataTask(with: request as URLRequest,completionHandler: { (data, response, error) in
                  if error==nil
                  {
                      DispatchQueue.main.async(execute: {
                          let dicResponse = try? JSONSerialization .jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
                          completionHandler(dicResponse, error==nil)
                      })
                  }
                  else
                  { 
                      completionHandler(nil, error==nil)
                  }
              })
              session.resume()
              }
          }
          **********************************use this in your view controller****************
          
          let dict : NSMutableDictionary = [:];
          
              dict["Your key"] = "your value"
              dict["Your key"] = "your value"
              dict["Your key"] = "your value"
          
              ApiConnection.postDataWithRequest(dict) { (response, status) in 
                  if(status){
                      print(response);
                  else{
                      print("failed webservice call");
                  }
              }
          

          ****************************************** Swift3.0************ ************************************

                  var objDic = [String: Any]()
                  let dic = NSMutableDictionary()
                  print(dic)
                  objDic["action"] = ""
                  objDic["product_id"] = self.peroductid
                  //            arrProduct .addObjects(from: objDic) as! Dictionary
                  print("\(objDic)")
          
          
                  Alamofire.request(Constant.Webservice_productinfo,
                                    method: HTTPMethod.post,
                                    parameters:objDic as? Parameters,
                                    encoding: JSONEncoding.default,
                                    headers: nil).responseJSON
          
          
                      {
                          (response:DataResponse<Any>) in
                          switch(response.result)
                          {
                          case .success(_):
                              if response.result.value != nil
                              {
                                    let status = response2?.object(forKey: "status") as! String?
          
                                  if status == "error"{}
          
                                  //finding the status from response
                                  var response2 = response.result.value as AnyObject?
                                      self.response1 = response.result.value as! NSDictionary
                                                          let type = 
                                (self.cartlistarray[0] as!NSDictionary)["base_image"]
                                                cell.productname.text = (self.cartlistarray[0] as!NSDictionary)["name"] as? String
          
              //Store the result value in swift 3.0
          
              UserDefaults.standard.set(userDetail.value(forKey: "email") as? NSString, forKey: "email")
                  if(UserDefaults.standard.object(forKey:"email") == nil){}
          //did select row click the data pass into  another view  
            let ProductListViewController = self.storyboard?.instantiateViewController(withIdentifier: "ProductListViewController") as! ProductListViewController         
           ProductListViewController.category_id = ((self.bannerarry[0] as? [String : String])?["cat_id"])!
          
          //or else callin from indexpath.row
          
                      item  = ((cartlistarray[indexpath.row] as? NSDictionary)?.value(forKey:"product_id") as! String?)!
          

          扩展 UIAlertController{

          func showErrorAlert(strMesage:NSString,VC:Any)
          {
              let alert = UIAlertController(title: "Demo App", message: strMesage as String, preferredStyle: UIAlertControllerStyle.alert)
              alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
              (VC as AnyObject).present(alert, animated: true, completion: nil)
          }
          

          } 扩展 UILabel{

          func setLabel(strTitle:String)
          {
              self.backgroundColor = UIColor.clear
              self.textColor = UIColor.white
              self.textAlignment = NSTextAlignment.left
              self.font = UIFont(name: "Avenir-Light", size: 15.0)
              self.font = UIFont.italicSystemFont(ofSize: 15)
              self.text=strTitle
          }
          

          }

           //image in to base 64 
          
           let image = imageCamera.image
                      let imageData:NSData = UIImageJPEGRepresentation(image!, 1.0)!as NSData
                      imageconvert = imageData.base64EncodedString(options: .lineLength64Characters)
                      base64formate = imageconvert.trimmingCharacters(in:CharacterSet.whitespaces)
                      print(base64formate)
          
          print data into profle view 
          
               let imageurl:String! =   SharedManager.sharedInstance().myMutableDict.value(forKey:"profileimg") as? String ?? "123"
              let url = URL(string: imageurl)
          
              DispatchQueue.global(qos: .userInitiated).async {
          
                  let imageData:NSData = NSData(contentsOf: url!)!
                  // When from background thread, UI needs to be updated on main_queue
                  DispatchQueue.main.async {
                      let image = UIImage(data: imageData as Data)
                      self.imageview.image = image
          
                  }
              }
          
          
                          let actionSheetController: UIAlertController = UIAlertController(title: "Magento Extension App", message:response1?.object(forKey: "message") as? String, preferredStyle: .alert)
                                      actionSheetController.addAction(UIAlertAction(title: "Ok", style: .default , handler:{ (UIAlertAction)in
                                          print("Ok button click")
                                      }))
                                      self.present(actionSheetController, animated: true, completion: nil)
                 }
          
                          case .failure(_):
          
                              print("error: \(response.result.error)")  // original 
                             URL request
                              break
                          }
                  }
          

          **************************objc******************** ************************************

           NSDictionary *objDic1 = @{@"mode":@"loginUser",
                                                 @"email":[result 
           objectForKey:@"email"],
                                                 @"password":@"",
                                                 };
                       // With AFNetworking
                       AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
                       manager.requestSerializer = [AFJSONRequestSerializer serializer];
                       [manager.requestSerializer setTimeoutInterval:100];
          
                       //    manager set
                       [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
          
                       [manager POST:WEBSERVICE_CALL_URL parameters:objDic1 progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable result) {
          
                           [SVProgressHUD dismiss];
          
                           NSLog(@"This s my response %@",result);
                           NSLog(@"success!");
          
                           if ([[result valueForKey:kStatus] isEqualToString:kOK])
                           {
                           }
                             }
                             failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error)
                        {
          }];
          ****************SDK LINK*******************************************
          https://github.com/AFNetworking/AFNetworking
          
          var userDetail = NSArray()
                                          userDetail = self.response1.value(forKey: "userData") as! NSArray
                                          print(userDetail)
          
           self.tmpDic = userDetail[0] as! NSDictionary
                                                  print(self.tmpDic)
          
                                                  var optionsdic = NSDictionary()
                                                  optionsdic = self.tmpDic.value(forKey:"options") as! NSDictionary
                                                  print(optionsdic)
          
                                                  self.arrayOfKeys = optionsdic.allKeys as NSArray
                                                  print(self.arrayOfKeys)
                                                  if (self.arrayOfKeys.contains("color"))
                                                  {
                                                      print("color")
          
                                                      self.colorarray = optionsdic.value(forKey:"color") as! NSArray
                                                      print(self.colorarray.count)
          
                                                      for index in 0..<self.colorarray.count
                                                      {
                                                          var dic = NSDictionary ()
                                                          dic = self.colorarray .object(at: index) as! NSDictionary
                                                          self.colorarrayobject .add(dic)
                                                          print(dic)
                                                      }
                                                      print(self.colorarrayobject)
          
                                                  }
                                                  else {
          
                                                      var defaultarray = NSArray()
                                                      defaultarray = optionsdic.value(forKey:"default") as! NSArray
                                                      print(defaultarray)
          
                                                      self.element0array = defaultarray[0] as! NSArray
                                                      print(self.element0array)
          
          
                                                      self.dic = self.element0array[0] as! NSDictionary
                                                      print(dic)
          
                                                      self.arr5 = self.dic .value(forKey: "values") as! NSArray
                                                      print(self.arr5)
          
                                                      for iteams in 0..<self.arr5.count
                                                      {
          
                                                          var type = String()
                                                          type = ((self.arr5[iteams]as! NSDictionary)["label"]! as? String)!
                                                          self.configeresizeaarray.append(type)
                                                      }
          
                                                      print("default")
          
                                                  }
          
                                              }
                                              self.imagearray   = self.array[0] as! NSArray
          
                                              for items in 0..<self.imagearray.count
                                              {
                                                  var type = String()
                                                  type = ((self.imagearray [items]as! NSDictionary)["image"]! as? String)!
                                                  self.cell0imagearray.append(type)
                                              }
                                              self.count = self.imagearray.count as Int
                                              self.configurePageControl()
                                              self.tableView.reloadData()
                                          }
                                          else
                                          {
          
                                          }
          
                                      }
                                      else
                                      {
          
                                      }
          

          【讨论】:

          • 答案与问题无关。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多