117

I'm trying to make a post request with a body in swift using Alamofire.

my json body looks like :

{
    "IdQuiz" : 102,
    "IdUser" : "iosclient",
    "User" : "iosclient",
    "List":[
        {
        "IdQuestion" : 5,
        "IdProposition": 2,
        "Time" : 32
        },
        {
        "IdQuestion" : 4,
        "IdProposition": 3,
        "Time" : 9
        }
    ]
}

I'm trying to make let list with NSDictionnary which look like :

[[Time: 30, IdQuestion: 6510, idProposition: 10], [Time: 30, IdQuestion: 8284, idProposition: 10]]

and my request using Alamofire looks like :

Alamofire.request(.POST, "http://myserver.com", parameters: ["IdQuiz":"102","IdUser":"iOSclient","User":"iOSClient","List":list ], encoding: .JSON)
            .response { request, response, data, error in
            let dataString = NSString(data: data!, encoding:NSUTF8StringEncoding)
                println(dataString)
        }

The request has an error and I believe the problem is with Dictionary list, cause if I make a request without the list it works fine, so any idea ?


I have tried the solution suggested but I'm facing the same problem :

 let json = ["List":list,"IdQuiz":"102","IdUser":"iOSclient","UserInformation":"iOSClient"]
        let data = NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted,error:nil)
        let jsons = NSString(data: data!, encoding: NSUTF8StringEncoding)



    Alamofire.request(.POST, "http://myserver.com", parameters: [:], encoding: .Custom({
        (convertible, params) in
        var mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
        mutableRequest.HTTPBody = jsons!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        return (mutableRequest, nil)
    }))
        .response { request, response, data, error in
        let dataString = NSString(data: data!, encoding:NSUTF8StringEncoding)
           println(dataString)
    }
Stranger B.
  • 9,004
  • 21
  • 71
  • 108
  • 3
    possible duplicate of [POST request with a simple string in body with Alamofire](http://stackoverflow.com/questions/27855319/post-request-with-a-simple-string-in-body-with-alamofire) – Bhavin Bhadani Aug 13 '15 at 07:56
  • 1
    Thanks for your comment, but the post your provided doesn't help, and I'm not trying to pass a string as body, so can you please read the post carefully – Stranger B. Aug 13 '15 at 08:30
  • @YasserB. Convert your JSON into a NSString (there is method for that), and then use the link of @Bhavin? – Larme Aug 13 '15 at 08:53
  • @Larme it would be really helpful if you provide an example – Stranger B. Aug 13 '15 at 09:15
  • @Larme I have tried the solution suggested but I have the same problem the request doesn't work unless I delete the list from the son body – Stranger B. Aug 13 '15 at 09:35

14 Answers14

197

If you are using Alamofire v4.0+ then the accepted answer would look like this:

let parameters: [String: Any] = [
    "IdQuiz" : 102,
    "IdUser" : "iosclient",
    "User" : "iosclient",
    "List": [
        [
            "IdQuestion" : 5,
            "IdProposition": 2,
            "Time" : 32
        ],
        [
            "IdQuestion" : 4,
            "IdProposition": 3,
            "Time" : 9
        ]
    ]
]

Alamofire.request("http://myserver.com", method: .post, parameters: parameters, encoding: JSONEncoding.default)
    .responseJSON { response in
        print(response)
    }
Gianni Carlo
  • 2,452
  • 1
  • 15
  • 18
108

You're close. The parameters dictionary formatting doesn't look correct. You should try the following:

let parameters: [String: AnyObject] = [
    "IdQuiz" : 102,
    "IdUser" : "iosclient",
    "User" : "iosclient",
    "List": [
        [
            "IdQuestion" : 5,
            "IdProposition": 2,
            "Time" : 32
        ],
        [
            "IdQuestion" : 4,
            "IdProposition": 3,
            "Time" : 9
        ]
    ]
]

Alamofire.request(.POST, "http://myserver.com", parameters: parameters, encoding: .JSON)
    .responseJSON { request, response, JSON, error in
        print(response)
        print(JSON)
        print(error)
    }

Hopefully that fixed your issue. If it doesn't, please reply and I'll adjust my answer accordingly.

cnoon
  • 16,575
  • 7
  • 58
  • 66
49

I don't like any of the other answers so far (except perhaps the one by SwiftDeveloper), because they either require you to deserialize your JSON, only for it to be serialized again, or care about the structure of the JSON itself.

The correct answer has been posted by afrodev in another question. You should go and upvote it.

Below is just my adaption, with some minor changes (primarily explicit UTF-8 charset).

let urlString = "https://example.org/some/api"
let json = "{\"What\":\"Ever\"}"

let url = URL(string: urlString)!
let jsonData = json.data(using: .utf8, allowLossyConversion: false)!

var request = URLRequest(url: url)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData

Alamofire.request(request).responseJSON {
    (response) in

    print(response)
}
Community
  • 1
  • 1
Sea Coast of Tibet
  • 5,055
  • 3
  • 26
  • 37
  • I agree that @SwiftDeveloper's answer is better and (to my opinion) more complete than the 'correct' one you mention. But I would argue two points. One, that the 'correct answer' that you mention has the flaw that `toJSONString` is not a native method, so it's basically a black box which you have to implement. Two, the answer you give, provides a var `json` which starts out as a json string, realistically nobody has the parameters that way, unless you are converting and storing them locally that way. – Gianni Carlo Mar 06 '17 at 22:49
  • @GianniCarlo 1) there's no `toJSONString` in my answer, 2) "realistically nobody has the parameters that way" - that's making a lot of assumptions; the JSON can be coming from quite different parts of the app, not related to making the request at all, and of which the networking code knows nothing. – Sea Coast of Tibet Mar 07 '17 at 08:52
  • Thanks for making my life easier!!!1 I 'm using Alamofire with Flask Backend. From Postman everything worked well.But from Alamofire it doesn't work. HTTP body and URL parameters and how to set them. Thanks again. – Vineel Dec 26 '18 at 23:19
19

Accepted answer in Xcode 11 - Swift 5 - Alamofire 5.0

func postRequest() {
    let parameters: [String: Any] = [
        "IdQuiz" : 102,
        "IdUser" : "iosclient",
        "User" : "iosclient",
        "List": [
            [
                "IdQuestion" : 5,
                "IdProposition": 2,
                "Time" : 32
            ],
            [
                "IdQuestion" : 4,
                "IdProposition": 3,
                "Time" : 9
            ]
        ]
    ]
    AF.request("http://myserver.com", method:.post, parameters: parameters,encoding: JSONEncoding.default) .responseJSON { (response) in
        print(response)
    }
}
Hari R Krishna
  • 782
  • 6
  • 20
11

If you are using swift4 and Alamofire v4.0 then the accepted code would look like this :

            let parameters: Parameters = [ "username" : email.text!, "password" : password.text! ]
            let urlString = "https://api.harridev.com/api/v1/login"
            let url = URL.init(string: urlString)
            Alamofire.request(url!, method: .put, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
                 switch response.result
                {
                case .success(let json):
                    let jsonData = json as! Any
                    print(jsonData)
                case .failure(let error):
                    self.errorFailer(error: error)
                }
            }
yasinkbas
  • 315
  • 3
  • 10
8

Xcode 8.X , Swift 3.X

Easy Use;

    let params:NSMutableDictionary? = [
    "IdQuiz" : 102,
    "IdUser" : "iosclient",
    "User" : "iosclient",
    "List": [
        [
            "IdQuestion" : 5,
            "IdProposition": 2,
            "Time" : 32
        ],
        [
            "IdQuestion" : 4,
            "IdProposition": 3,
            "Time" : 9
        ]
    ]
];
            let ulr =  NSURL(string:"http://myserver.com" as String)
            let request = NSMutableURLRequest(url: ulr! as URL)
            request.httpMethod = "POST"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            let data = try! JSONSerialization.data(withJSONObject: params!, options: JSONSerialization.WritingOptions.prettyPrinted)

            let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
            if let json = json {
                print(json)
            }
            request.httpBody = json!.data(using: String.Encoding.utf8.rawValue);


            Alamofire.request(request as! URLRequestConvertible)
                .responseJSON { response in
                    // do whatever you want here
                   print(response.request)  
                   print(response.response) 
                   print(response.data) 
                   print(response.result)

            }
SwiftDeveloper
  • 7,244
  • 14
  • 56
  • 85
5

Alamofire 5.5 and Swift 5

func postRequest() {
  let parameters: [String : Any] = [
    "IdQuiz" : 102,
    "IdUser" : "iosclient",
    "User" : "iosclient",
    "List": [
      [
        "IdQuestion" : 5,
        "IdProposition": 2,
        "Time" : 32
      ],
      [
        "IdQuestion" : 4,
        "IdProposition": 3,
        "Time": 9
      ]
    ]
  ]
  
  let url = URL(string: "http://myserver.com/api/post")!
  AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
    .validate()
    .responseJSON { response in
      switch response.result {
      case .success(let response):
        print(response)
      case .failure(let error):
        print(error.localizedDescription)
      }
  }
}
Suhit Patil
  • 11,748
  • 3
  • 50
  • 60
4

I've slightly edited SwiftDeveloper's answer, because it wasn't working for me. I added Alamofire validation as well.

let body: NSMutableDictionary? = [
    "name": "\(nameLabel.text!)",
    "phone": "\(phoneLabel.text!))"]

let url = NSURL(string: "http://server.com" as String)
var request = URLRequest(url: url! as URL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let data = try! JSONSerialization.data(withJSONObject: body!, options: JSONSerialization.WritingOptions.prettyPrinted)

let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
if let json = json {
    print(json)
}
request.httpBody = json!.data(using: String.Encoding.utf8.rawValue)
let alamoRequest = Alamofire.request(request as URLRequestConvertible)
alamoRequest.validate(statusCode: 200..<300)
alamoRequest.responseString { response in

    switch response.result {
        case .success:
            ...
        case .failure(let error):
            ...
    }
}
effeKtSVK
  • 125
  • 1
  • 11
2

There are few changes I would like to notify. You can access request, JSON, error from response object from now on.

        let urlstring = "Add URL String here"
        let parameters: [String: AnyObject] = [
            "IdQuiz" : 102,
            "IdUser" : "iosclient",
            "User" : "iosclient",
            "List": [
                [
                    "IdQuestion" : 5,
                    "IdProposition": 2,
                    "Time" : 32
                ],
                [
                    "IdQuestion" : 4,
                    "IdProposition": 3,
                    "Time" : 9
                ]
            ]
        ]

        Alamofire.request(.POST, urlstring, parameters: parameters, encoding: .JSON).responseJSON { response in
            print(response.request)  // original URL request
            print(response.response) // URL response
            print(response.data)     // server data
            print(response.result)   // result of response serialization

            if let JSON = response.result.value {
                print("JSON: \(JSON)")
            }
            response.result.error
        }
Kiran Jasvanee
  • 6,362
  • 1
  • 36
  • 52
2

Alamofire Fetch data with POST,Parameter and Headers

func feedbackApi(){
    DispatchQueue.main.async {
        let headers = [
            "Content-Type": "application/x-www-form-urlencoded",
            "Authorization": "------"
        ]
        let url = URL(string: "---------")
        var parameters = [String:AnyObject]()
        parameters =  [
            "device_id":"-----" as AnyObject,
            "user_id":"----" as AnyObject,
            "cinema_id":"-----" as AnyObject,
            "session_id":"-----" as AnyObject,
        ]
       Alamofire.request(url!, method: .post, parameters: parameters,headers:headers).responseJSON { response in
                switch response.result{
                case.success(let data):
                    self.myResponse = JSON(data)
                    print(self.myResponse as Any)
                    let slide = self.myResponse!["sliders"]
                    print(slide)
                    print(slide.count)
                    for i in 0..<slide.count{
                        let single = Sliders(sliderJson: slide[i])
                        self.slidersArray.append(single)
                    }
                    DispatchQueue.main.async {
                        self.getSliderCollection.reloadData()
                    }
                case .failure(let error):
                    print("dddd",error)
                }

        }
    }

}
Tony Franzis
  • 489
  • 5
  • 6
1

Here is how I created Http POST request with swift that needs parameters with Json encoding and with headers.

Created API Client BKCAPIClient as a shared instance which will include all types of requests such as POST, GET, PUT, DELETE etc.

func postRequest(url:String, params:Parameters?, headers:HTTPHeaders?, completion:@escaping (_ responseData:Result<Any>?, _ error:Error?)->Void){
    Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON {
        response in
        guard response.result.isSuccess,
            (response.result.value != nil) else {
                debugPrint("Error while fetching data: \(String(describing: response.result.error))")
                completion(nil,response.result.error)
                return
        }
        completion(response.result,nil)
    }
}

Created Operation class that contains all data needed for particular request and also contains parsing logic inside completion block.

func requestAccountOperation(completion: @escaping ( (_ result:Any?, _ error:Error?) -> Void)){
    BKCApiClient.shared.postRequest(url: BKCConstants().bkcUrl, params: self.parametrs(), headers: self.headers()) { (result, error) in
        if(error != nil){
            //Parse and save to DB/Singletons.
        }
        completion(result, error)
    }
}
func parametrs()->Parameters{
    return ["userid”:”xnmtyrdx”,”bcode":"HDF"] as Parameters
}
func headers()->HTTPHeaders{
    return ["Authorization": "Basic bXl1c2VyOm15cGFzcw",
            "Content-Type": "application/json"] as HTTPHeaders
}

Call API In any View Controller where we need this data

func callToAPIOperation(){
let accOperation: AccountRequestOperation = AccountRequestOperation()
accOperation.requestAccountOperation{(result, error) in

}}
vinodonkar
  • 59
  • 5
1

If anyone wondering how to proceed with models and stuff, see below

        var itemArr: [Dictionary<String, String>] = []
        for model in models {
              let object = ["param1": model.param1,
                            "param2": model.param2]
              itemArr.append(object as! [String : String])
        }

        let param = ["field1": someValue,
                     "field2": someValue,
                     "field3": itemArr] as [String : Any]

        let url: URLConvertible = "http://------"

        Alamofire.request(url, method: .post, parameters: param, encoding: JSONEncoding.default)
            .responseJSON { response in
                self.isLoading = false
                switch response.result {
                case .success:
                    break
                case .failure:
                    break
                }
        }
Heshan Sandeepa
  • 3,388
  • 2
  • 35
  • 45
0
func get_Contact_list()
{
    ApiUtillity.sharedInstance.showSVProgressHUD(text: "Loading..")
    let cont_nunber = contact_array as NSArray
    print(cont_nunber)

    let token = UserDefaults.standard.string(forKey: "vAuthToken")!
    let apiToken = "Bearer \(token)"


    let headers = [
        "Vauthtoken": apiToken,
        "content-type": "application/json"
    ]

    let myArray: [Any] = cont_nunber as! [Any]
    let jsonData: Data? = try? JSONSerialization.data(withJSONObject: myArray, options: .prettyPrinted)
    //        var jsonString: String = nil
    var jsonString = String()
    if let aData = jsonData {
        jsonString = String(data: aData, encoding: .utf8)!
    }

    let url1 = "URL"
    var request = URLRequest(url: URL(string: url1)!)
    request.httpMethod = "POST"
    request.allHTTPHeaderFields = headers
    request.httpBody = jsonData as! Data

    //        let session = URLSession.shared

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("error=\(String(describing: error))")
            ApiUtillity.sharedInstance.dismissSVProgressHUD()
            return
        }

        print("response = \(String(describing: response))")


        let responseString = String(data: data, encoding: .utf8)
        print("responseString = \(String(describing: responseString))")

        let json =  self.convertStringToDictionary(text: responseString!)! as NSDictionary
        print(json)

        let status = json.value(forKey: "status") as! Int

        if status == 200
        {

            let array = (json.value(forKey: "data") as! NSArray).mutableCopy() as! NSMutableArray


        }
        else if status == 401
        {
            ApiUtillity.sharedInstance.dismissSVProgressHUD()

        }
        else
        {
            ApiUtillity.sharedInstance.dismissSVProgressHUD()
        }


    }
    task.resume()
}

func convertStringToDictionary(text: String) -> [String:AnyObject]? {
    if let data = text.data(using: String.Encoding.utf8) {
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]
            return json
        } catch {
            print("Something went wrong")
        }
    }
    return nil
}
Jignesh
  • 23
  • 5
0

Alamofire ~5.2 and Swift 5

You can structure your parameter data

Work with fake json api

struct Parameter: Encodable {
     let token: String = "xxxxxxxxxx"
     let data: Dictionary = [
        "id": "personNickname",
        "email": "internetEmail",
        "gender": "personGender",
     ]
}

 let parameters = Parameter()

 AF.request("https://app.fakejson.com/q", method: .post, parameters: parameters).responseJSON { response in
            print(response)
        }
Trần Hữu Hiền
  • 872
  • 1
  • 9
  • 22