Send JSON array as a parameter Alamofire - swift

I'm having difficulty with a parameter which contains a Json array using Alamofire
Here is a string of my Json:
"[{\"id\":546836102,\"count\":1},{\"id\":216479424,\"count\":1}]"
Here is my code where I make the request:
let data = (params["cart"] as! String).data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : .fragmentsAllowed) as? [Dictionary<String, Int>] {
let parameters: Parameters = [
"address_id": params["address_id"] as! Int,
"delivery_day": params["delivery_day"] as! String,
"delivery_hour": params["delivery_hour"] as! Int,
"cart": jsonArray,
"via": params["via"] as! String
]
Alamofire.request(Global.baseURL + "orders/finish", method: .post, parameters: parameters, encoding: URLEncoding.default, headers: header)
.responseSwiftyJSON {
Printing out my parameters
["cart": [["id": 546836102, "count": 1], ["count": 1, "id": 216479424]], "address_id": 641589205, "delivery_day": "1399-01-20", "delivery_hour": 21, "via": "ios"]
Backend must receive the cart as below:
[
{
"id": 123456,
"count": 2
},
{
"id": 654321,
"count": 3
}
]
But instead it gets the data like this:
{
"delivery_hour" : "21",
"delivery_day" : "1399-01-20",
"cart" : [
{
"count" : "1"
},
{
"id" : "546836102"
},
{
"count" : "1"
},
{
"id" : "216479424"
}
],
"via" : "ios",
"address_id" : "641589205"
}
I have tried JSONEncoding and URLEncoding options by Alamofire but nothing seems to work and this is the closest I've gotten to the API template so far.
What am I doing so wrong here?
// MARK: - Update
So I updated to the latest version of Alamofire and still no good results :(
Here is the code:
let payload = MyParameters(address_id: 641589205, delivery_day: "1399-01-21", delivery_hour: 21, cart: items, via: "ios")
AF.request(url, method: .post, parameters: payload, encoder: JSONParameterEncoder.default, headers: .init(header), interceptor: nil).response { dataResponse in
switch dataResponse.result {
case .success(let value):
if dataResponse.response?.statusCode == 200 {
let json = JSON(value!)
completionHandler(json, nil)
} else {
print(dataResponse.response?.statusCode ?? -1)
}
case .failure(let error):
print(error)
completionHandler(nil, error.localizedDescription)
}
}
My payload looks exactly what I want it to be
{
"cart" : [
{
"count" : 1,
"id" : 546836102
},
{
"count" : 1,
"id" : 216479424
}
],
"via" : "ios",
"address_id" : 641589205,
"delivery_day" : "1399-01-21",
"delivery_hour" : 21
}
But then again the endpoint receives this:
{
"{\"delivery_day\":\"1399-01-21\",\"address_id\":641589205,\"delivery_hour\":21,\"cart\":" : {
"{\"id\":546836102,\"count\":1},{\"id\":216479424,\"count\":1}" : null
}
}

Using Alamofire 4, you can't send arrays using the method you've shown, as the Parameters type is [String: Any]. You're also not using the correct ParameterEncoding. If you want to send a JSON body, you need to use the JSONEncoding. What you can do is manually serialize the array into a URLRequest and make that request using Alamofire.
Additionally, if you update to Alamofire 5, Encodable parameters are now supported, so you if you can define your parameters as an Encodable type, sending them would be as easy as passing an array.
AF.request(..., parameters: [some, encodable, values], encoder: JSONEncoder.default)...

Related

How to send an array of json as value for multipart/form-data content type?

Guys I need to send parameters described in the image value where content type is multipart/form-data. Im having difficulty in sending only package_json parameter.
The problem is I don't know how do I send multiple package_json values as parameter? I can send one value like this:
let param = [
"outletId : "1",
"vehicleId" : "1",
"instructions" : tvInstructions.text,
"package_json" : "[{\"packageId\":\"1\"}]",
"addressId" : "1"
]
Above i'm able to send package_json = [{"packageId": 1}] as String as my function below sends parameters as [String : String] and images of Data type as [String : Any]. Im having problem sending multiple values in package_json. For eg. something like this: [{"packageId": 1}, {"packageId": 2}, {"packageId": 3}] and so on. Here's the function that i'm using to send parameters:
func postrequest(_ request: String, onPath imagesData:[Data]?,_ imageName : String, andParameter parameters: [String:String]?, withCompletion response: #escaping serviceCompletion) {
let headers: HTTPHeaders
headers = ["Content-type": "multipart/form-data"]
AF.upload(multipartFormData: { multiPart in
if let allParams = parameters {
for (key, value) in allParams {
multiPart.append(value.data(using: .utf8)!, withName: key)
}
}
for imageData in imagesData ?? [] {
multiPart.append(imageData, withName: "\(imageName)", fileName: "file.jpg", mimeType: "image/jpg")
}
}, to: request, usingThreshold: UInt64.init(),
method: .post,
headers: headers).response { (res) in
if((res.error == nil)){
do {
response(res.data,res.error)
}
}
else{
// hideHud()
response(res.data,res.error)
}
}
}
I tried to convert function to send [String: Any] data but found out we can only send as [String : String] along with images as [String : Any].
I just want to know if there is any way to modify "package_json" : "[{\"packageId\":\"1\"}]" so I can send [{"packageId": 1}, {"packageId": 2}, {"packageId": 3}]?
Just in case, this is how im calling above function and sending parameters:
func sendData() {
let param = [
"outletId" : "1",
"vehicleId" : "1",
"instructions" : tvInstructions.text,
"package_json" : "[{\"packageId\":\"1\"}]",
"addressId" : "1"
]
ApiNetworkManager.shared.postrequest(Api.completeUrl, onPath: [], "", andParameter: param) { (response, err) in
ApiNetworkManager.shared.hideHud()
debugPrint(param)
let json = JSON.init(response!)
debugPrint(json)
if err == nil {
if err == nil && response != nil {
if json.dictionaryValue["success"]?.stringValue == "1" {
//Add your code here
}
else{
let message = json.dictionaryValue["message"]?.stringValue
self.showAlert(Message: message ?? "Error")
}
} else {
// hideHud()
print(err?.localizedDescription as Any)
let message = json.dictionaryValue["message"]?.stringValue
self.showAlert(Message: message ?? "Error")
}
}
else{
ApiNetworkManager.shared.hideHud()
let message = err?.localizedDescription
self.showAlert(Message: message ?? "Error")
}
}
}

Swift: convert [Dictionary<String, [String : Double]>.Element] to [String : [String : Double]]

I have this JSON string:
[
{
"name": "first_category",
"model": {
"OK": 0.49404761904761907,
"NOPE": 0.48214285714285715
}
},
{
"name": "second_category",
"model": {
"YOP": 0.389338593,
"GO": 0.20420894
}
}
]
I have created this struct to decode it:
struct JSONModel: Codable {
let name: String
let model: [String: Double]
}
The decoding:
let decodedModel = try? decoder.decode([JSONModel].self, from: Data(jsonString.utf8))
It correctly fills the array as expected, but now I would like to use this array to create a dictionary whose keys would be the JSONModel names, and values the models. This is what I expect to get:
[
"first_category": [
"OK": 0.49404761904761907,
"NOPE": 0.4821428571428571
],
"second_category": [
"YOP": 0.389338593,
"GO": 0.20420894
]
]
So I tried this:
let simplifiedModel: [String: [String: Double]] = decodedModel.flatMap { [$0.name: $0.model] }
But I'm getting this error:
Cannot convert value of type '[Dictionary<String, [String : Double]>.Element]' to closure result type '[String : [String : Double]]'
What should I do instead?
Thank you for your help
I would use reduce(into:) for this
let dictionary = decodedModel.reduce(into: [:]) {
$0[$1.name] = $1.model
}

Alamofire sending parameter array with key and multiple value

I need to do this in my project:
multiple values in multiple array common key for parameter
Some links that have the same question but no exact answers, I always see posts that have answers like use a custom encoding and that's it.
https://github.com/Alamofire/Alamofire/issues/570
i have 4 array :
var imagesArray: [UIImage] = [], var DayOpreation: [String] = [],varDayOffStart: [String] = [], var DayOffEnd: [String] = []
and this my code :
let parameters : Parameters = [
"about": self.descriptionLabel.text!,
"address" : addressLabel.text!,
"country" : "1",
"state": "1",
"city" : "1",
"postcode" : self.postalCode.text!,
"policies": self.policiesLabel.text,
"longitude" : "",
"latitude" : "",
"available_24hours": "0",
"open_hour" : "09:00",
"closed_hour" : "18:00",
"operating_days[0]": "Senin",
"days_off[0][start]" : "2019-10-10",
"days_off[0][end]" : "2019-10-15",
]
let token = UserDefaults.standard.string(forKey: UserDefaultConstant.ACCESS_TOKEN)
let headers = ["key": "\(token!)"
]
let ImageData = UIImageView()
ImageData.image = UIImage(named: "rectangle-1")
let imgData = UIImagePNGRepresentation(ImageData.image!)!
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "photo_profile[0]",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
},
to:"\(Endpoints.BASE)\(Endpoints.UPDATE_VENDOR)",
method: .post,
headers: headers,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
if let data = response.data {
guard let json = try? JSON(data: data) else { return }
let messageRoom = json["message"].string
print("listOfficialRoom== ",json)
}
}
case .failure(let encodingError):
print(encodingError)
}
})
Use Paramaters in Alamofire, something like this
let daysOff = [String: Any]() // array of dictionaries for days off
for (i, day) in days.enumerated() {
let dayOff: Parameters = [
"start": day.start,
"end": day.end
]
daysOff["\(i)"] = dayOff
}
let parameters: Parameters = [
"open_hour": "...",
"closed_hour": "...",
"days_off": daysOff
]

How to post JSON with Array of Dictionaries : Alamofire

i want to post array of dictionaries in alamofire, but some how it is not posting.i can use many ways but still not find the proper answer on it. Showing error "Extra argument 'method' in call" . Here is my code.
let userToken: HTTPHeaders = [
"Content-Type": "application/json"
]
let parm = [
[
"EmployeeID": id,
"Longitude": longitude,
"Latitude": latitude,
"GeoTime": dateString,
"UserToken": "g98XQdy8B}rQ7?Q"
]
]
postAttandance(apiUrl: postAttandanceURL, parameter: parm , tiket: userToken){
(done) -> Void in
if done{
}
}
func postAttandance(apiUrl : String , parameter : [[String : Any]] , tiket : HTTPHeaders , completion : #escaping (_ done : Bool) -> Void ){
Alamofire.request(apiUrl, method : .post , parameters : parameter ,encoding : JSONEncoding.default, headers : tiket).responseJSON { (response) in
if response.result.isSuccess{
let responsejson : JSON = JSON(response.result.value!)
completion(true)
}
}
}

How to make PUT request in Alamofire in swift 4

I am new to swift and Alamofire, I had a data from services that we are publishing in tableviews, but there is an option for the user to edit the data displaying in tableviews. Edited data should update the service and publish edited new data to the tableviews.
Data from service:
[
{
"Id": 1,
"Name": "Sr",
"designation": "",
"officeLandLine": "456123789",
"officeMobile": "789456",
"officeEmail": "klm#mail.com",
"personalEmail": "",
"address": ""
},
{
"Id": 2,
"Name": "S",
"designation": "D",
"officeLandLine": "0863",
"officeMobile": "810",
"officeEmail": "dy#gov.in",
"personalEmail": "",
"address": ""
},
Please try this:
func serviceCallForUpdateData(withSelectedIndex index: Int){
let param = ["id" : self.arry[index].id, "name" : self.arry[index].name]
let requestURL = "your url"
print("***************************** URL: *********************************\(requestURL)")
Alamofire.request(requestURL, method: .put, parameters: param as? Parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { (responseJson) in
print("Response : \(responseJson)")
if (responseJson.result.isSuccess){
let dictRes = responseJson.result.value as! NSDictionary
completion(["res":dictRes, "stats":1] as AnyObject?)
} else {
let res : NSDictionary = ["msg":"Network Error"]
completion(["res":res, "stats":0] as AnyObject?)
}
}
}
call this function in didSelect method of table view.
You can get the data from the array didSelect method.
In dedSelect method please write:
self.serviceCallForUpdateData(index : indexPath.row)
It may helps you.Thank you.