如何使用NSURLSession在Swift中解析JSON

16

我试图解析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中无法正常工作。

5个回答

37

不要为已解码的对象声明 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()
}

4

这里是苹果公司宣布。

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=由于应用传输安全策略需要使用安全连接,因此无法加载资源。})

希望这有所帮助!


我也使用了这段代码,但是出现了“表达式类型不明确”的错误,需要更多的上下文信息。 - Vipulk617
看看我的代码。请在你的代码中删除 throws。谢谢! - Long Pham
我会在PlayGround上测试它。稍等一下。 - Long Pham
更新代码可以正常运行而没有编译错误,但是当我们在以下代码块中编写代码时:do { let json:AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary print(json) } catch let error as NSError { // 错误处理 print(error?.localizedDescription) }会出现错误。 - Vipulk617
我稍后会看你的问题。现在我很忙 :p - Long Pham

2

使用URLSession进行Swift 4 Web服务调用,使用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()
    }

0
这里是使用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()

-6

1) 在你的项目中创建 ApiConnection 类.. import Foundation class 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**************************************************

**************************Objective-C**************************************************

 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
                            {

                            }

与问题无关的答案。 - Unterbelichtet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接