如何使用 Swift 检索响应 JSON 数据

How to retrieve response JSON data with Swift

我正在尝试使用 Yelp API 并根据搜索词接收相应的 JSON。这是我正在使用的 YelpAPI 客户端:

import Foundation
import UIKit

let yelpConsumerKey = "KLGXXXXfnmhQ"
let yelpConsumerSecret = "wPmXXXXvOA"
let yelpToken = "0-3DsXXXXhAq"
let yelpTokenSecret = "BViXXXXQ-Dz3Y"

class YelpClient: BDBOAuth1RequestOperationManager {
    var accessToken: String!
    var accessSecret: String!

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    class var sharedInstance : YelpClient {
        struct Static {
            static var token : dispatch_once_t = 0
            static var instance : YelpClient? = nil
        }
        dispatch_once(&Static.token) {
            Static.instance = YelpClient(consumerKey: yelpConsumerKey, consumerSecret: yelpConsumerSecret, accessToken: yelpToken, accessSecret: yelpTokenSecret)
        }
        return Static.instance!
    }

    init(consumerKey key: String!, consumerSecret secret: String!, accessToken: String!, accessSecret: String!) {
        self.accessToken = accessToken
        self.accessSecret = accessSecret
        var baseUrl = NSURL(string: "http://api.yelp.com/v2/")
        super.init(baseURL: baseUrl, consumerKey: key, consumerSecret: secret);

        var token = BDBOAuthToken(token: accessToken, secret: accessSecret, expiration: nil)
        self.requestSerializer.saveAccessToken(token)
    }

    func searchWithTerm(term: String, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, NSError!) -> Void) -> AFHTTPRequestOperation! {
        // For additional parameters, see http://www.yelp.com/developers/documentation/v2/search_api
        var parameters = ["term": term, "ll": "37.77493,-122.419415"]
        return self.GET("search", parameters: parameters, success: success, failure: failure)
    }

    func searchWithTerm(term: String, deal: Bool, radius: Int, sort: Int, categories: String, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, NSError!) -> Void) -> AFHTTPRequestOperation! {
        // For additional parameters, see http://www.yelp.com/developers/documentation/v2/search_api
        var parameters = NSDictionary()
        if (radius == -1) {
            parameters = ["term": term, "ll": "37.77493,-122.419415", "deals_filter": deal, "sort": sort, "category_filter":categories]
        }
        else {
            var meter:Double = Double(radius) * 1609.34
            parameters = ["term": term, "ll": "37.77493,-122.419415", "deals_filter": deal, "radius_filter": meter, "sort": sort, "category_filter":categories]
        }
        return self.GET("search", parameters: parameters as [NSObject : AnyObject], success: success, failure: failure)
    }


}

我为这里的餐厅做了一个模型class:

import UIKit

class Resturant: NSObject {
    var name: String!
    var thumbUrl: String!
    var address: String!
    var jsonData: NSData!

    init(dictionary: NSDictionary) {
        name = dictionary["name"] as? String
        thumbUrl = dictionary["thumbUrl"] as? String
        address = dictionary["address"] as? String
    }

    class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
        YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
            println(response)
        let JSONObject = NSJSONSerialization.JSONObjectWithData(response as! NSData, options: NSJSONReadingOptions(0), error: nil)
            }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in

        }
    }
}

let JSONObject = NSJSONSerialization.JSONObjectWithData(response as! NSData, options: NSJSONReadingOptions(0), error: nil)

这行代码提示这个错误:

Could not cast value of type '__NSCFDictionary' (0x10b914a60) to 'NSData' (0x10b913a48).

您正在收到回复 JSON。只是它是一个二值化的 NSData 对象,如果我没记错的话,您可能希望将其转换为 JSON 对象。现在,我猜它会打印出难以辨认的字母数字字符块,对吧?

嗯,你可以这样做:

class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
        YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
            println(response) //Illegible block of data
            let JSONObject = NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions(0), error: nil)
             println(JSONObject)//Prints JSON

            }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in

        }
    }

编辑#1

看起来是错误请求的情况。明确客户和服务器之间为此工作的合同。必须有一些可能丢失的参数或一些意外的请求。恐怕我们帮不了你,因为我们不知道那份合同是什么。

编辑 #2

此时代码...

let JSONObject = NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions(0), error: nil)

... API 接受响应类型 NSData。但是,您的回复类型是 NSDictionary。它会给你一个警告;但是在编译时没有类型检查,它编译。但是运行时试图将 response 视为 NSData,但事实并非如此;它实际上是 NSDictionary,崩溃。

只需记录 NSDictionary。你会得到结果。

编辑 #3 你的最终代码应该是这样的:

class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
            YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
                println(response) //Illegible block of data
                let responseInfo = response as! NSDictionary
                println(responseInfo)
                //Prints JSON

                }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in

            }
        }