JSON 不可转换为 void (Openweathermap API)

Posted

技术标签:

【中文标题】JSON 不可转换为 void (Openweathermap API)【英文标题】:JSON is not convertible to void (Openweather map API) 【发布时间】:2015-08-21 08:45:33 【问题描述】:

我正在使用 Swift 调用 Openweather 地图 API,我需要从响应中返回一个特定值作为字符串。

但是,当我尝试返回值时,由于 JSON 无法转换为字符串,因此出现错误。

func callWeatherServ(name:String, completion:(Dictionary<String,AnyObject>) -> Void)

    var baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"

    var url: String = "\(baseUrl)?q=\(name)"

    let finalUrl: NSURL = NSURL(string: url)!

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(finalUrl, completionHandler: data, response, error -> Void in
        if error != nil
        
            // If there is an error in the web request, print it to the console
            println(error.localizedDescription)
        

        var err: NSError?
        var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
        if err != nil
        
            // If there is an error parsing JSON, print it to the console
            println("JSON Error \(err!.localizedDescription)")
        

        let json = JSON(jsonResult)
        println("response is \(json) ")

        var  weathername = json["weather"][0]["main"]

        if (weathername != nil)
        
            return weathername

        
    )
    task.resume()

我明白了,因为我们使用了返回类型为 void 的闭包,所以我们应该使用完成处理程序。但我不知道我们如何做到这一点。

如果我们将完成处理程序作为参数传递,我们如何调用函数?

【问题讨论】:

How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest的可能重复 completion(weathername) 而不是return weathername 然后使用我的示例链接中的完成调用您的函数。另外要小心,您似乎要解析 JSON 两次,一次使用 NSJSONSerialization,一次使用 SwiftyJSON... @Eric 很抱歉,我无法将我的示例与您的示例联系起来,因为我是学习 swift 的新手。您能否仅用我的示例指导我。 【参考方案1】:

如果您想继续使用示例中的 SwiftyJSON,请按以下步骤操作:

将完成处理程序的类型从字典更改为 SwiftyJSON 使用的 JSON 类型。

然后将要“返回”的值包装在处理程序中。

然后按照我的示例调用您的方法,并带有尾随闭包

斯威夫特 2

func callWeatherServ(name:String, completion:(object: JSON) -> Void) 
    let baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"
    let url: String = "\(baseUrl)?q=\(name)"
    if let finalUrl = NSURL(string: url) 
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(finalUrl, completionHandler: data, response, error -> Void in
            if let error = error 
                print(error.localizedDescription)
             else 
                if let data = data 
                    let json = JSON(data: data)
                    print("response is \(json) ")
                    completion(object: json["weather"][0]["main"])
                 else 
                    print("No data")
                
            
        )
        task.resume()
    

调用方法:

callWeatherServ("paris")  (object) in
    // here you get back your JSON object
    print(object)

请注意,您使用 NSJSONSerialization 和 SwiftyJSON 解析了两次数据,因此我删除了不必要的 NSJSONSerialization 部分。

原始 Swift 1 版本

func callWeatherServ(name:String, completion:(object: JSON) -> Void)

    var baseUrl: String = "http://api.openweathermap.org/data/2.5/weather"

    var url: String = "\(baseUrl)?q=\(name)"

    let finalUrl: NSURL = NSURL(string: url)!

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(finalUrl, completionHandler: data, response, error -> Void in
        if error != nil
        
            // If there is an error in the web request, print it to the console
            println(error.localizedDescription)
        

        var err: NSError?
        let json = JSON(data: data, options: NSJSONReadingOptions.allZeros, error: &err)
        println("response is \(json) ")

        var  weathername = json["weather"][0]["main"]

        if (weathername != nil)
        
            completion(object: weathername)

        
    )
    task.resume()

调用方法:

callWeatherServ("paris", completion:  (object) -> Void in
    println(object)  // "Clear"
)

【讨论】:

【参考方案2】:

在您调用此方法的位置实现完成处理程序,并在该位置使用字符串,无需返回字符串。

您可以通过在调用者函数中实现它来直接从完成句柄中使用它

【讨论】:

@Eric 对于我创建的任何类型,它都会给出相同的消息 json 不能转换为该类型。 //@mihir,如果你能提供一个真正有助于消除我疑虑的例子。 你能从你调用这个方法的地方添加代码并突出显示给你这个错误的行吗? callWeatherServ(name, completion: (responseDictionary) -&gt; Void in // use responseDictionary here println(responseDictionary) ) `` let json = JSON(jsonResult) println("response is \(json) ") var weathername:Dictionary&lt;String,AnyObject&gt; = json["weather"][0]["main"] if (weathername != nil) completion(weathername) 这是我尝试按照 eric 的建议更改类型的方式 @RichaPathak 你不能从返回类型为 void 的方法返回。

以上是关于JSON 不可转换为 void (Openweathermap API)的主要内容,如果未能解决你的问题,请参考以下文章

Alamofire Void 不可转换为响应

Alamofire 库 Void 不能转换为 Response<AnyObject, NSError> -> Void

类型 '() => void' 不可分配给类型 '() => '

如何将json转换为字符串数组

如何将 NSString 从 JSON 转换为 NSDictionary? [关闭]

将 JSON 格式的 NSString 转换为 NSArray 失败