Json key/value incorrectly formatted - swift

Trying to login to a web service as such:
let parameters: Parameters = [
"Password":password,
"Username":username
]
var headers:HTTPHeaders = commonHeaders()
headers["Content-Type"] = "application/json;charset=UTF-8"
Alamofire.request(url!, method:.post, parameters:parameters, headers:headers).responseJSON { response in
....
}
Somehow, my parameters end up on the server side as
"Username=xxx&Password=yyy"
where
{"Username":"xxx","Password":"yyy"}
is expected
This must be something simple, but I hope you can help me

Add the type of encoding you want your parameters to be in your request, Default is .URLEncoding. So, your parameters are going like "Username=xxx&Password=yyy"(appended into url)
Add the parameter json encoding to your request:
Alamofire.request(url!, method:.post, parameters:parameters, headers:headers, encoding: JSONEncoding.default)

Related

Alamofire syntax for ecobee request

I'm trying to find the correct syntax for calling ecobee's API from Swift 4 using Alamofire.
Their cURL example:
curl -H "Content-Type: text/json" -H "Authorization: Bearer ACCESS_TOKEN" 'https://api.ecobee.com/1/thermostat?format=json&body=\{"selection":\{"selectionType":"registered","selectionMatch":"","includeRuntime":true\}\}'
The closest I've been to a solution is this
func doRequest() {
guard let url = URL(string: "https://api.ecobee.com/1/thermostat?format=json") else { return }
let parameters: Parameters = [
"selection": [
"selectionType": "registered",
"selectionMatch": ""
]
]
let headers: HTTPHeaders = [
"Content-Type": "text/json",
"Authorization": "Bearer \(core.accessToken)"
]
let req = AF.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
print("Error:", response.error?.localizedDescription ?? "no error")
print("Data:", String(data: response.data!, encoding: .utf8)!)
}
debugPrint(req)
}
When I run this, the call ultimately fails with status code 408, a server timeout.
When I change the HTTP method to use .post, the call completes, but the response is an internal status 3 with message "Update failed due to a communication error."
Can anyone help me figure out what I'm doing wrong before I waste another day trying to hack my way through it?
Ecobee's request format is a bit bizarre, as it uses form encoded parameters, but one of the values is a JSON encoded body. You'll have to do a little bit of prep work, as Alamofire doesn't naturally support something like this. This is just sample code, you'll need to do the work to make it safer.
First, encode the JSON parameters and get the String value:
let jsonParameters = ["selection": ["selectionType": "registered", "selectionMatch": ""]]
let jsonData = try! JSONEncoder().encode(jsonParameters)
let jsonString = String(decoding: jsonData, as: UTF8.self)
Then, create the actual parameters and headers values:
let parameters = ["format": "json", "body": jsonString]
let token = "token"
let headers: HTTPHeaders = [.authorization(bearerToken: token), .contentType("text/json")]
let url = URL(string: "https://api.ecobee.com/1/thermostat")!
And make the request:
AF.request(url, parameters: parameters, headers: headers).responseJSON { response in ... }

Can't make post request using params as dictionary with Swift 4 & Alamofire

I'm trying to learn to call API with/without library. But the problem here confuses me.
I have params like this:
let parameters: [String:String] =
["key":"MY_KEY" ,
"q":sourceText,
"source": sourceLanguage),
"target": target)]
let headers: HTTPHeaders = [ "Content-type": "application/json"]
I make a post call like this:
Alamofire.request(urlString, method: HTTPMethod.post, parameters: parameters, headers: headers)
.responseJSON{ response in
guard response.result.error == nil else {
print("error calling POST on /todos/1")
print(response.result.error!)
return
}
// make sure we got some JSON since that's what we expect
guard let json = response.result.value as? [String: Any] else {
print("didn't get todo object as JSON from API")
print("Error: \(response.result.error)")
return
}
By this I get an error 403, saying that I do not have a valid API key (I tested the key with postman, and it is okay).
After many efforts, I have to change the code like this
let stringparams = "key=MY_KEY&q=\(sourceText)&source=\(sourceLanguage)&target=\(target)"
request.httpBody = stringparams.data(using: String.Encoding.utf8)
and using this: Alamofire.request(request)
it works!
I'm using Google Cloud Translation api. And the web use a REST api as said here: https://cloud.google.com/translate/docs/reference/translate
So why can't I use params as dictionary, but using the string (like formdata) will work here?
My guess is Alamofire didn't make the right BODY for the request from the parameters because other arguments is okay. But I don't know why.
And I think Google should accept a json params as they mentioned, in stead of using form data? I did try the original method, but it didn't work with JSON.
From what actually works for you it looks like you need to encode the parameters in the same style as a query. Try this:
struct ParameterQueryEncoding: ParameterEncoding {
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var request = try urlRequest.asURLRequest()
request.httpBody = parameters?
.map { "\($0)=\($1)" }
.joined(separator: "&")
.data(using: .utf8)
return request
}
}
You should then be able to perform the original call that you had before:
Alamofire.request(urlString,
method: HTTPMethod.post,
parameters: parameters,
encoding: ParameterQueryEncoding(),
headers: headers)
.responseJSON { response in
...
}
Try by using JSON encoding. Make sure you have removed ) from dictionary.
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)

Alamofire POST request URL

Suppose i have a URL "http://aewfwfpi.staginwwedwfg.dewfewf.io/mobile/v1/network/station/10/timetablesss"
where 10 in the above URL is the stationId and can be any number .
How can i POST a request with changing parameter(StationId) in the URL using alamofire?
Should i add it in Parameter section?
Please help
Currently am calling it statically like below:-
Alamofire.request(
"http://aewfwfpi.staginwwedwfg.dewfewf.io/mobile/v1/network/station/10/timetablesss",
parameters:nil,
headers: nil)
var id = 123
var yourURL = "http://aewfwfpi.staginwwedwfg.dewfewf.io/mobile/v1/network/station/\(id)/timetablesss"
use \(variableName) to insert variables or constants in a string
Headers is where you specify the format of the content that you want to send and receive.
example of headers:
let headers: HTTPHeaders = [
"Accept": "application/json",
"Content-Type": "application/json"
]
Parameters is where you put the data that you want to send (POST)
example of parameters:
let pararameters: [String, Any] = [
"name": name as String,
"id": id as Int,
]
To do a POST request, add the parameters to the body of the request and not the url itself.
Something like below is what you must follow:
let parameters: Parameters = ["parameter-name": parameterValue]
let headers = ["Content-Type":"application/json"]
Alamofire.request("<your post url>",method: .post, parameters: parameters, encoding: JSONEncoding.default,headers: headers)
.responseJSON { response in
print(response)
// Do anything you like with the response here
}

How to add Alamofire URL parameters

I have a working scenario using Postman passing in URL parameters. Now when I try to do it via Alamofire in Swift, it does not work.
How would you create this url in Alamofire?
http://localhost:8080/?test=123
_url = "http://localhost:8080/"
let parameters: Parameters = [
"test": "123"
]
Alamofire.request(_url,
method: .post,
parameters: parameters,
encoding: URLEncoding.default,
headers: headers
The problem is that you're using URLEncoding.default. Alamofire interprets URLEncoding.default differently depending on the HTTP method you're using.
For GET, HEAD, and DELETE requests, URLEncoding.default encodes the parameters as a query string and adds it to the URL, but for any other method (such as POST) the parameters get encoded as a query string and sent as the body of the HTTP request.
In order to use a query string in a POST request, you need to change your encoding argument to URLEncoding(destination: .queryString).
You can see more details about how Alamofire handles request parameters here.
Your code should look like:
_url = "http://localhost:8080/"
let parameters: Parameters = [
"test": "123"
]
Alamofire.request(_url,
method: .post,
parameters: parameters,
encoding: URLEncoding(destination: .queryString),
headers: headers)
If you want your parameters to be used in querystring, use .queryString as URLEncoding, as in:
(I assume you have headers somewhere)
let _url = "http://localhost:8080/"
let parameters: Parameters = [
"test": "123"
]
Alamofire.request(_url,
method: .post,
parameters: parameters,
encoding: URLEncoding.queryString,
headers: headers)
This form is suggested by Alamofire author because it's more coincise to the other, see screenshot:
See original here

How can I send only a string value as the parameter in a POST network call using Alamofire?

So lets say instead of this,
let parameters: [String: Any] = [
"settings":
[
"username" : UILabel.text,
"password": textField.text,
],
]
Alamofire.request("myURL", method: .post, parameters: parameter, encoding:)
.responseJSON { response in
print(response)
}
I would like to know if I could send only a string as the parameter like this,
let parameter: String
parameter = "SampleString"
Alamofire.request("myURL", method: .post, parameters: parameter).responseJSON{ response in
print(response)
}
Try this
var params = "{\"username\": \"\(UILabel.text)\"}"
Alamofire.request(url, method:.post, parameters:[params]).responseJSON { response in
debugPrint(response)
}
I think your parameters always need to be of type dictionary, so that you have a key,value pair.
If you simply want to have one key, you can do this:
let parameter = ["parameterName": parameterValue]
Hope that helps!