How to send multiple JSON objects as a stream using alamofire - json

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)
}
}

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.

Unable to Upload Image and add parameters with POST method multipart/form-data in Swift

Below is the URL requirement for this API: http://itaag-env-1.ap-south-1.elasticbeanstalk.com/editprofile/
according to this answer Upload image with multipart form-data iOS in Swift
I have tried below code, but i am unable to add parameters to POST Request and i am unable to call uploadImage method in viewdidload
Here is the code:
func uploadImage(paramName: String, fileName: String, image: UIImage) {
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/editprofile/")
let boundary = UUID().uuidString
let deviceId: String = "HardcodeDEVICEIDforiTaag222"
let headers = ["deviceid": "deviceId","userType": "personal","key": "5fe42fb3b54543a0bab5667cf96526f8"]
let parameters: [String: Any] = ["firstName":"Satish", "lastName":"Madhavarapu","gender":"male", "ageGroup":"40-50"]
let session = URLSession.shared
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = headers as! [String : String]
// Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
// And the boundary is also set here
urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
// Add the image data to the raw http request data
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(paramName)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
data.append(image.pngData()!)
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
// Send a POST request to the URL, with the data we created earlier
session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
if error == nil {
let jsonData = try? JSONSerialization.jsonObject(with: responseData!, options: .allowFragments)
if let json = jsonData as? [String: Any] {
print(json)
}
}
}).resume()
}
in the above code i am unable to add parameters let parameters: [String: Any] = ["firstName":"Satish", "lastName":"Madhavarapu","gender":"male", "ageGroup":"40-50"] to urlRequest
And How to call uploadImage in viewDidLoad
Please help me with code

Alamofire 4, Swift 3 and building a json body

{"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)
}

Swift2 handle data from POST

Im sending a Post message to my database with swift. But how do i handle the data from that response? My variable responseString looks like this now. I want to get each parameter and work with them.
Optional([{"id":"9","name":"hallow","strasse":"street","tel_nr":"123456789","kommentar":"comment"}])
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost/getByName.php")!)
request.HTTPMethod = "POST"
let postString = "name=hallow"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
Your php is returning an array containing a dictionary, so you'd have to access it like
if let responsedict = response.first {
print(responsedict["id"])
}// prints 9
(if you know there's going to be no other elements returned first is ok...or change how your data is sent back).
You could take it one step further and parse the response in to a model e.g.
let person = Person(id: response.first?["id"], name: response.first?["name"], etc)
print("id \(person.id)")
//id 9

Global functions to post and get API data in swift

I am trying to make my POST and GET API request methods global so that I need not repeat the call procedure repetitively. For this, I created a swift file and made two functions for POST API and GET API, but can't figure out how to pass data from calling class to the called class, and return back the response to the calling class. My code which needs to be integrated in a separate swift file is :
let request = NSMutableURLRequest(URL: NSURL(string: "http://api.quickblox.com/users.json")!)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("0.1.1", forHTTPHeaderField: "QuickBlox-REST-API-Version")
request.setValue(tokenSet, forHTTPHeaderField: "QB-Token")
request.HTTPMethod = "POST"
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(dict, options: [])
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
I need to pass API Url and a request data in the form of a dictionary, to, say postApiRequest() and getApiRequest() methods. How do I create swift file for the same and call it elsewhere.