Alamofire 4, Swift 3 and building a json body - json

{"title":"exampleTitle","hashTags":[{"name":"tag1"},{"name":"tag2"}],"uploadFiles":
[{"fileBytes":"seriesOfBytes\n","filename":"upload.txt"}]}
That is my desired body I want to send to the backend.
I'm using Swift 3.0 and Alamofire 4 and i have multiple questions.
first, How do i correctly create a body which contains values and arrays of values?
My approach is:
let para:NSMutableDictionary = NSMutableDictionary()
para.setValue("exampleTitle", forKey: "title")
let jsonData = try! JSONSerialization.data(withJSONObject: para, options: .init(rawValue: 0))
let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue) as! String
print(jsonString)
which gives me
{"title":"exampleTitle"}
second, my alamofire .post request looks like the following and is not working:
Alamofire.request(postURL, method: .post, parameters: jsonString, encoding: JSONEncoding.default)
.responseJSON { response in
debugPrint(response)
}
i get the error message: extra argument 'method' in call. If i instead of jsonString use a string of the type
var jsonString: [String : Any]
it does work, but i do not know how to put the body into this type.
summary
looking for help (example would be the best) on how to create the body, and how to send it via Alamofire 4 and swift 3 to my backend.

You need to pass parameter as [String:Any] dictionary, so create one dictionary as your passing JSON like this.
let params = [
"title":"exampleTitle",
"hashTags": [["name":"tag1"],["name":"tag2"]],
"uploadFiles":[["fileBytes":"seriesOfBytes\n","filename":"upload.txt"]]
]
Now pass this params as parameter in Alamofire request.
Alamofire.request(postURL, method: .post, parameters: params, encoding: JSONEncoding.default)
.responseJSON { response in
debugPrint(response)
}

Related

Alamofire POST not working as expected. Error on parameters

I am trying to upload (post) a JSON string using Alamofire and I'm getting an error that leads me to believe there is some issue in the dictionary encoding.
The array I am encoding is an array of objects, all of type String. It looks like this:
class SavedDeliveries: Codable { //not sure if this is the issue (I use this to store default values locally)
var fullName = ""
var address = ""
var city = ""
var zip = ""
var phone = ""
var orders = ""
var ordersListed = ""
var pickup = ""
}
The code including the Alamofire call looks like this:
func postData() {
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"X-Master-Key": "xxx", //API Key
"X-Bin-Name": "deliverydata"]
let jsonEncoder = JSONEncoder()
let jsonData = try! jsonEncoder.encode(deliveryList)
let json = String(data: jsonData, encoding: String.Encoding.utf8)
print(json!) // printing the JSON and it is correct when validated.
AF.request("https://api.jsonbin.io/v3/b", method: .post, parameters: json, encoding: JSONEncoding.default, headers: headers).responseString { (response) in
switch response.result {
case .success:
print("was successful")
case let .failure(error):
print(error)
}
}
}
I expect it to upload the JSON file but I'm getting an error message that says this:
Cannot convert value of type 'String?' to expected argument type 'Parameters?' (aka 'Optional<Dictionary<String, Any>>')
Not sure if the AF call parameter is expecting a certain kind of dictionary key:value format. If this is not the right call format for uploading JSON, what do I need to change?
Thanks for any help. I'm not a full-time Swift developer but manage an app that is usually within my capabilities. This one has me stumped.
I guess I don't understand much about HTTP requests or Alamofire, but I was able to solve this issue with the following mods to my code (without Alamofire, which seems like overkill in this case).
func postData() {
// Prepare URL
let url = URL(string: "https://api.jsonbin.io/v3/b")
guard let requestUrl = url else { fatalError() }
// Prepare URL Request Object
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// Set HTTP Request Body
let header: HTTPHeaders = [
"Content-Type": "application/json",
"X-Master-Key": "xxx",
"X-Bin-Name": "deliverydata"
]
request.headers = header
let jsonEncoder = JSONEncoder()
let jsonData = try! jsonEncoder.encode(deliveryList)
let json = String(data: jsonData, encoding: String.Encoding.utf8)
request.httpBody = json!.data(using: String.Encoding.utf8)
// Perform HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
// Convert HTTP Response Data to a String
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
}
task.resume()
}
To make such a request using Alamofire, I'd recommend:
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"X-Master-Key": "xxx", //API Key
"X-Bin-Name": "deliverydata"]
AF.request("https://api.jsonbin.io/v3/b",
method: .post,
parameters: deliveryList,
headers: headers).responseString { response in
switch response.result {
case .success:
print("was successful")
case let .failure(error):
print(error)
}
}
Even better, create a Decodable response type and use responseDecodable to parse it.
I would also suggest not using empty strings as your default values, that can easily lead to sending bad or invalid data to the backend.

How do I use JSON element with alamofire

I am using two textfields to pass login information to the PHP web service using Alamofire in the following way.
#IBAction func LoginButton(_ sender: Any) {
//getting the username and password
let parameters: Parameters=[
"Name":TextFieldUserName.text!,
"Pass":TextFieldPassword.text!
]
Alamofire.request(URL_USER_LOGIN, method: .post, parameters: parameters).responseJSON
{
response in
//printing response
print(response)
The following Json data is received on login.
[{"code":0,"message":"Check Username and Password....","userid":""}]
I want to use either "code" value (0 for false and 1 for true) or "message" value as String to put into an if - else statement for further steps. If Alamofire is not the best way to go about this, can someone please show another way. Thanks in advance for the help.
Do you need to deserialize the response from the server?
The easiest option is parsing response value as NSDictionary
if let JSON = response.result.value as? NSDictionary {
let code = JSON.value(forKey: "code") as? Int
let message = JSON.value(forKey: "message") as? String
}
You can also use the Codable protocol and the JSONDecoder to decode this response into your structure.
For example, declare struct:
struct LoginResponse: Codable {
var code: Int
var message: String
}
and decode response using JSONDecoder
let jsonDecoder = JSONDecoder()
let loginResponse = try? jsonDecoder.decode(LoginResponse.self, from: response.data)

How to send multiple JSON objects as a stream using alamofire

I want to send multiple different JSON object in a single request, i felt streaming the multiple JSON objects like a file in a single request would be better, so kindly let me know if it is possible, if so kindly give me an idea of how to do it using Alamofire, Below is the formate of the raw body (application/json) data that i want to post
{"a":23214,"b":54674,"c":"aa12234","d":4634}
{"a":32214,"b":324674,"c":"as344234","d":23434}
{"a":567214,"b":89674,"c":"sdf54234","d"34634}
I tried the below code, but it didn't work as the body param is not in the correct format, that's the reason i want to try sending the multiple JSON objects as a stream in a single request, Kindly advice
let SendParams = [
["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]
]
_ = Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding, headers: header)
JSON format is not correct for your request, JSON is always key-value pair, where key is always String, and value is any Object. In your example need to set key at top level for object of type Array as below:
let SendParams = [
"key" :[["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]]
]
_ = Alamofire.request(url, method: .post, parameters: SendParams, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in}
OR
Serialise the array and set as httpBody of URLRequest object:
let url = YOUR_POST_API_URL
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let values = [
["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]
]
request.httpBody = try! JSONSerialization.data(withJSONObject: values)
Alamofire.request(request)
.responseJSON { response in
// do whatever you want here
switch response.result {
case .failure(let error):
print(error)
if let data = response.data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
case .success(let responseObject):
print(responseObject)
}
}

JSON.dictionaryObject is null in Alamofire swift 3

I have a JSON in following format:
postJson ={"firstname":"Vishal","lastname":"raskar","username":"vishal123","password":"123456","confirmpassword":"123456","email":"raskarvishal7#gmail.com","timezone":"1","accountid":"12345","phoneno":"8655012753"}
(Data type of postJson is JSON i.e swiftyJSON)
Now I want to hit on server through Alamofire, so I need to Post JSON data in dictionary format in parameters : ___, e.g.:
Alamofire.request(URL, method: .post, parameters: postJson.dictionaryObject, encoding: JSONEncoding.default,headers: "Content-Type": "application/json").responseJSON { response in switch response.result {
case .success(let data):
case .failure(let error):
}
so basically I tried to convert my JSON in dictionary by postJson.dictionaryObject. But always gets null from postJson.dictionaryObject (even though data is present in postJson).
I tried all combinations like postJson.dictionaryValue, postJson.dictionary, but no success.
I then tried to convert postJson to Data, and then dictionary:
if let data = postJson.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject]
}
catch {
print(error.localizedDescription)
}
}
and then post through Alamofire, now getting response. What am I doing wrong? I want to use my first option.
Assuming you are using Swift 3 / Alamofire 4.0
This is how you would define the "parameters" parameter according to Alamofire documentation:
let parameters: Parameters = ["foo": "bar"]
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
}
To learn more, click here

not receiving json Data in Alamofire request with http body

Im using the following code to send a POST request to the web server with an http parameter, in order to receive the JSON Data
Alamofire.request(.POST,myURL, parameters: [:], encoding: .Custom({
(convertible, params) in
var mutableRequest = convertible.URLRequest.copy() as NSMutableURLRequest
mutableRequest.HTTPBody = "MyBody".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
return (mutableRequest, nil)
}))
ive got it from stackoverflow : POST request with a simple string in body with Alamofire
but im not receiving any data.
im using swift 2.3 and alamofire 3.5.
Any help?
simple POST call with Alamofire4 & Swift3 :
let url: String = "https://example.com"
let parameter = ["X": "10", "Y": "20"]
Alamofire.request(url, method: .post, parameters: parameter, encoding: URLEncoding.default, headers: nil)
.responseJSON { (response) in
let result = response.result.value
print(result)
}
simple GET call to see some JSON result :
let url: String = "https://example.com"
Alamofire.request(url)
.responseJSON { response in
let result = response.result.value
print(result)
}