S Graham
S Graham

Reputation: 232

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.

Upvotes: 0

Views: 512

Answers (2)

Jon Shier
Jon Shier

Reputation: 12770

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.

Upvotes: 0

S Graham
S Graham

Reputation: 232

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

Upvotes: 0

Related Questions