post 请求的 NSURLSession 序列化错误
NSURLSession serialization error with post request
我正在尝试获取 Instagram 的访问令牌,但经常出现错误 You must provide client id
。 我认为这是一个序列化问题,因为我的参数没有正确序列化。
我在 POSTMAN
上试过了,它运行良好,但在 NSURLSession
上它会抛出错误。
错误
{
code = 400;
"error_message" = "You must provide a client_id";
"error_type" = OAuthException;
}
我在序列化时哪里做错了。
let instaInfoDict = NSDictionary(objects: ["client_id","client_secret","grant_type","redirect_uri","code"], forKeys: [kCLientIdInstagram,kCLientSecretIdInstagram,"authorization_code",kRedirectUriInstagram,code])
// Hit post request with params
WebServices().postRequest(kAccessTokenGenerationInstagram, bodyData: instaInfoDict, completionBlock: { (responseData) in
print(responseData)
})
//WEBSERVICE CLASS:
func postRequest(url:String, bodyData:NSDictionary, completionBlock:WSCompletionBlock){
if let url = NSURL(string: url){
let headers = [
"Accept": "application/json",
"content-type": "application/json"]
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 10)
request.HTTPMethod = "POST"
request.allHTTPHeaderFields = headers
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: [.PrettyPrinted])
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
if error != nil {
// Handle error
completionBlock!(responseData:nil)
}
else{
//Parsing the data
let parsedData = parseJson(response as? NSData)
completionBlock!(responseData: parsedData)
}
})
task.resume()
}
}
这个我也试过了
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: NSJSONWritingOptions(rawValue: 0))
似乎问题在于 Content-Type 应该是 application/x-www-form-urlencoded
而不是 application/json
,而且使用这种 Content-Type 发送参数的方式也有一点变化。
我做了一个小测试,这段代码对我有用:
static func generateAccessToken() {
let params = ["client_id": "your_id",
"client_secret": "your_client_secret",
"grant_type": "authorization_code",
"redirect_uri": "http://tolkianaa.blogspot.com/",
"code": "the_code"]
guard let url = NSURL(string: "https://api.instagram.com/oauth/access_token") else {
return
}
let request = NSMutableURLRequest(URL: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let stringParams = params.paramsString()
let dataParams = stringParams.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let paramsLength = String(format: "%d", dataParams!.length)
request.setValue(paramsLength, forHTTPHeaderField: "Content-Length")
request.HTTPBody = dataParams
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
var json: AnyObject = [:]
guard let data = data else {
return
}
do {
json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
} catch {
// Do nothing
}
print(json)
}
task.resume()
}
为了获取字符串形式的参数,我做了这个扩展:
extension Dictionary {
func paramsString() -> String {
var paramsString = [String]()
for (key, value) in self {
guard let stringValue = value as? String, let stringKey = key as? String else {
return ""
}
paramsString += [stringKey + "=" + "\(stringValue)"]
}
return (paramsString.isEmpty ? "" : paramsString.joinWithSeparator("&"))
}
}
希望对您有所帮助!
我正在尝试获取 Instagram 的访问令牌,但经常出现错误 You must provide client id
。 我认为这是一个序列化问题,因为我的参数没有正确序列化。
我在 POSTMAN
上试过了,它运行良好,但在 NSURLSession
上它会抛出错误。
错误
{
code = 400;
"error_message" = "You must provide a client_id";
"error_type" = OAuthException;
}
我在序列化时哪里做错了。
let instaInfoDict = NSDictionary(objects: ["client_id","client_secret","grant_type","redirect_uri","code"], forKeys: [kCLientIdInstagram,kCLientSecretIdInstagram,"authorization_code",kRedirectUriInstagram,code])
// Hit post request with params
WebServices().postRequest(kAccessTokenGenerationInstagram, bodyData: instaInfoDict, completionBlock: { (responseData) in
print(responseData)
})
//WEBSERVICE CLASS:
func postRequest(url:String, bodyData:NSDictionary, completionBlock:WSCompletionBlock){
if let url = NSURL(string: url){
let headers = [
"Accept": "application/json",
"content-type": "application/json"]
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 10)
request.HTTPMethod = "POST"
request.allHTTPHeaderFields = headers
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: [.PrettyPrinted])
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
if error != nil {
// Handle error
completionBlock!(responseData:nil)
}
else{
//Parsing the data
let parsedData = parseJson(response as? NSData)
completionBlock!(responseData: parsedData)
}
})
task.resume()
}
}
这个我也试过了
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: NSJSONWritingOptions(rawValue: 0))
似乎问题在于 Content-Type 应该是 application/x-www-form-urlencoded
而不是 application/json
,而且使用这种 Content-Type 发送参数的方式也有一点变化。
我做了一个小测试,这段代码对我有用:
static func generateAccessToken() {
let params = ["client_id": "your_id",
"client_secret": "your_client_secret",
"grant_type": "authorization_code",
"redirect_uri": "http://tolkianaa.blogspot.com/",
"code": "the_code"]
guard let url = NSURL(string: "https://api.instagram.com/oauth/access_token") else {
return
}
let request = NSMutableURLRequest(URL: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let stringParams = params.paramsString()
let dataParams = stringParams.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let paramsLength = String(format: "%d", dataParams!.length)
request.setValue(paramsLength, forHTTPHeaderField: "Content-Length")
request.HTTPBody = dataParams
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
var json: AnyObject = [:]
guard let data = data else {
return
}
do {
json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
} catch {
// Do nothing
}
print(json)
}
task.resume()
}
为了获取字符串形式的参数,我做了这个扩展:
extension Dictionary {
func paramsString() -> String {
var paramsString = [String]()
for (key, value) in self {
guard let stringValue = value as? String, let stringKey = key as? String else {
return ""
}
paramsString += [stringKey + "=" + "\(stringValue)"]
}
return (paramsString.isEmpty ? "" : paramsString.joinWithSeparator("&"))
}
}
希望对您有所帮助!