how to send array parameter using alamofire - swift

I'm trying to make a post request with a body array in swift using Alamofire
postman like
and here my code
class func storeEventContact(_ id:String, type_contact:String, user_id: Int, firstname:String, lastname: String,completionHandler:RequestCompletionHandler?){
let url = "\(Endpoints.BASE)\(Endpoints.INVITE_STORE)"
let params:NSMutableDictionary? = ["id": id,
"type_contact":type_contact,
"contacts": ["user_id" : user_id, "firstname" : firstname, "lastname" : lastname]]
self.postRequest(url: url, parameters: params as? [String : Any]) { (result, error) in
self.postRequest(url: url, parameters: params as? [String : Any]) { (result, error) in
if error != nil{
completionHandler?(result, error)
return
}
let baseResponse = Mapper<BaseResponse>().map(JSONObject: result)
if !baseResponse!.status{
completionHandler?(baseResponse, error)
return
}
completionHandler?(result, error)
}
}
}

You just need to define an array, you are almost there, just need an extra set of [] in your dictionary.
let params = ["id": id,
"type_contact":type_contact,
"contacts": [
[
"user_id": user_id,
"firstname": firstname,
"lastname": lastname
]]]

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

Send JSON array as a parameter Alamofire

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

How to post array of dictionary with alamofire in swift?

I have to post array of dictionary value like this.
{
"reservedHour": "2019-11-01T14:55+0900",
"reservedBoxSize": "sm",
"products": [{
"id": 312
}],
"boxArea": {
"id": 66
},
"type": "RENT"
}
products is Array of Json Object.
So I try this.
func requestReserveAvailableDate(type: String, reserveHour: String, boxAreaID: Int, boxSize: String, productIDs: [Int], completionHandler: #escaping (_ availableDates: [String]?, _ errorMessage: String?) -> Void) {
let parameters: [String: Any] = ["type": type,
"reservedHour": reserveHour,
"boxArea": ["id": boxAreaID],
"reservedBoxSize": boxSize,
"products": productIDs.map({ ["id": $0] })]
...
But this is not working.
I am using alamofire only for all API calls. Please help me how I can solve it.
Just try like this
var parameters: [String: Any] = [:]
parameters = ["type": type,
"reservedHour": reserveHour,
"reservedBoxSize": boxSize,
"boxArea": [],
"products": []]
var boxAreaParams:[String:Any] = [:]
boxAreaParams = ["id": boxAreaID]
parameters["boxArea"] = boxAreaParams
var productsParmas: [string: Any] = [:]
productParams = ["id": productId]
var product = parameter["products"] as? [[String: Any]] ?? [[String: Any]]()
product.append(productParams)
parameters["product"] = product

how to store the response of a service in a model with alamofire

I am learning to programme in swift, I developed with android previously the consumption of services and stored them in a model with the help of retrofit and serializable. Now in swift, I use the Alamofire 4.0 and SwiftyJson to consume a service and the problem is how to save all the response JSON in a model and then use this data, I have reviewed several examples but I still do not understand how to do it.
Could you tell me how to do it or what I need to add to complete this action to get the information and then use it
so I consume the service
static func loginService(email : String, password : String, completionHandler : #escaping (LoginResponse) -> Void){
let parameters : Parameters = ["email": email, "password": password]
Alamofire.request(AlamofireConstants.LOGIN, method: .post, parameters: parameters, encoding: URLEncoding.default).validate(statusCode: 200..<300).responseData { response in
switch response.result {
case .failure(let error):
print("error ==> \(error)")
case .success(let data):
do{
let result = try JSONDecoder().decode(LoginResponse.self, from: data)
print(result)
} catch {
print(error)
}
}
}
}
this is my model
struct LoginResponse : Decodable {
let user : User?
let status: Int
let success: Bool
let message: String
}
struct User : Decodable {
let id: Int
let firstName, lastName, surName, email: String
let emailToken: String?
let validate: String
let token, nationality, documentType, documentNumber: String?
let legalName, legalNumber, birthdate: String?
let gender: String
let phoneMovil, phoneFix, icon: String?
let wishOffers, acceptTerms, isCustomer: Int
let active: Bool
let createdAt, updatedAt: String
}
and this is the json from response
{
"user": {
"id": 183,
"first_name": "teste",
"last_name": "testet",
"sur_name": "este",
"email": "adeveloper964#gmail.com",
"email_token": null,
"validate": "S",
"token": null,
"nationality": null,
"document_type": null,
"document_number": null,
"legal_name": null,
"legal_number": null,
"birthdate": null,
"gender": "O",
"phone_movil": null,
"phone_fix": null,
"icon": null,
"wish_offers": 0,
"accept_terms": 1,
"is_customer": 0,
"active": true,
"created_at": "2019-05-13 17:04:50",
"updated_at": "2019-05-14 10:19:31"
},
"status": 0,
"success": true,
"message": ""
}
I get this error
keyNotFound(CodingKeys(stringValue: "firstName", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "user", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"firstName\", intValue: nil) (\"firstName\").", underlyingError: nil))
Why SwiftyJSON? You don't need that. To parse JSON into a model Decodable is much easier to use and it's built-in (no dependencies).
struct LoginResponse : Decodable {
let user: User
let status: Int
let success : Bool
let message : String
}
struct User : Decodable {
let id : Int
let firstName, lastName, surName, email : String
}
static func loginService(user : String, password : String){
Alamofire.request(AlamofireConstants.BASE_URL_TEST + "/api/loginuser", method: .post, parameters: ["email":user,"password":password], encoding: URLEncoding.default)
.validate(statusCode: 200..<300)
.responseData { response in // note the change to responseData
switch response.result {
case .failure(let error):
print(error)
case .success(let data):
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(LoginResponse.self, from: data)
print(result)
} catch { print(error) }
}
}
}
import SwiftyJSON in the class where you wrote loginService API and under success case write:
case .success(let value):
let json = JSON(value)
let loginModel = LoginResponse(json: json)
print("Login Model is: \(loginModel)")
and see if it works

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.