Como enviar uma solicitação POST com BODY rapidamente

97

Estou tentando fazer um post request com um corpo em swift usando Alamofire.

meu corpo json se parece com:

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

Estou tentando fazer let listcom que NSDictionnary se pareça com:

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

e minha solicitação usando Alamofire se parece com:

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

A solicitação tem um erro e acredito que o problema seja com a lista do Dicionário, pois se eu fizer uma solicitação sem a lista funciona bem, então alguma ideia?


Tentei a solução sugerida, mas estou enfrentando o mesmo problema:

 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.
fonte
3
possível duplicata da solicitação POST com uma string simples no corpo com Alamofire
EI Captain v2.0
1
Obrigado pelo seu comentário, mas a postagem que você forneceu não ajuda, e eu não estou tentando passar uma string como corpo, então você pode, por favor, ler a postagem com atenção
Stranger B.
@YasserB. Converta seu JSON em um NSString (existe um método para isso), e então use o link de @Bhavin?
Larme de
@Larme, seria muito útil se você fornecer um exemplo
Stranger B.
@Larme Eu tentei a solução sugerida, mas tenho o mesmo problema a solicitação não funciona a menos que eu exclua a lista do corpo filho
Estranho B.

Respostas:

97

Você está perto. A formatação do dicionário de parâmetros não parece correta. Você deve tentar o seguinte:

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

Esperançosamente, isso resolveu seu problema. Se isso não acontecer, responda e ajustarei minha resposta de acordo.

tarde
fonte
Como faço para definir alguma propriedade do meu JSON para null, já que não posso atribuir nila AnyObject?
Amp Tanawat de
3
@JaseemAbbas verifique sua versão do Alamofire, se você estiver na v4.0 + verifique minha resposta abaixo
Gianni Carlo
como enviar este tipo de parâmetro caso a codificação seja .urlEncoding
Pramod Shukla
1
Não é possível converter o valor do tipo 'Int' para o tipo de valor de dicionário esperado 'AnyObject'
myatmins
como fazer se digamos que o valor do parâmetro "List" tem cerca de 1000 elementos de lista?
Nishad Arora
175

Se você estiver usando o Alamofire v4.0 +, a resposta aceita seria esta:

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
fonte
6
Ótimo! Altere a resposta aceita para esta, por favor! :) ou combine com o atual para as soluções Alamofire 3 e 4.
Tom van Zummeren
1
Concordo - é a declaração explícita de JSONEncodingpara desambiguar o tipo que fez isso por mim.
Thomas Verbeek
@Gianni Carlo usei o mesmo que sua resposta, mas em minha resposta de sucesso estou recebendo erros.
Ramakrishna
@Ramakrishna que pode estar relacionado à API que você está consumindo. Para analisar a resposta, geralmente uso a biblioteca SwiftyJSON, diga-me que tipo de erros você está recebendo
Gianni Carlo
Obrigado pela sua resposta. Eu tenho a solução.
Ramakrishna
34

Eu não gosto de nenhuma das outras respostas até agora (exceto talvez aquela por SwiftDeveloper), porque quer exigir que você desserializar seu JSON, apenas para que ele seja serializado novamente, ou se preocupam com a estrutura do próprio JSON.

A resposta correta foi postada por afrodev em outra pergunta. Você deve ir e votar positivamente.

Abaixo está apenas a minha adaptação, com algumas pequenas alterações (principalmente conjunto de caracteres UTF-8 explícito).

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)
}
Costa do Mar do Tibete
fonte
Concordo que a resposta de @SwiftDeveloper é melhor e (na minha opinião) mais completa do que a 'correta' que você mencionou. Mas eu argumentaria dois pontos. Um, que a 'resposta correta' que você mencionou tem a falha que toJSONStringnão é um método nativo, então é basicamente uma caixa preta que você tem que implementar. Dois, a resposta que você dá fornece uma var jsonque começa como uma string json, realisticamente, ninguém tem os parâmetros dessa forma, a menos que você os esteja convertendo e armazenando localmente dessa forma.
Gianni Carlo
@GianniCarlo 1) não há toJSONStringna minha resposta, 2) "realisticamente, ninguém tem os parâmetros dessa maneira" - isso é fazer muitas suposições; o JSON pode estar vindo de partes bem diferentes do aplicativo, não relacionadas a fazer a solicitação e sobre as quais o código de rede não sabe nada.
Costa do
Obrigado por tornar minha vida mais fácil !!! 1 Estou usando o Alamofire com Flask Backend. De Postman tudo funcionou bem. Mas de Alamofire não funciona. Parâmetros de URL e corpo HTTP e como defini-los. Obrigado novamente.
Vineel
8

Xcode 8.X, Swift 3.X

Uso fácil;

    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
fonte
7

Se você estiver usando o swift4e Alamofire v4.0o código aceito será parecido com este:

            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)
                }
            }
Mohammed Ali Khaled
fonte
5

Resposta aceita no 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
fonte
4

Eu editei ligeiramente a resposta do SwiftDeveloper , porque não estava funcionando para mim. Eu adicionei a validação Alamofire também.

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
fonte
1
Ainda funciona no Alamofire 4.9.1 e Swift 5.1. Muito apreciado
Abe
2

Existem algumas mudanças que eu gostaria de notificar. Você pode acessar a solicitação, JSON, erro do objeto de resposta a partir de agora.

        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
fonte
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
fonte
1

Aqui está como criei uma solicitação Http POST com swift que precisa de parâmetros com codificação Json e com cabeçalhos.

Cliente API criado BKCAPIClient como uma instância compartilhada que incluirá todos os tipos de solicitações, como 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)
    }
}

Classe de operação criada que contém todos os dados necessários para uma solicitação específica e também contém lógica de análise dentro do bloco de conclusão.

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 em qualquer View Controller onde precisamos desses dados

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

}}
vinodonkar
fonte
1
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 ZestBrains
fonte
1

Se alguém está se perguntando como proceder com modelos e outras coisas, veja abaixo

        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
fonte
0

Alamofire ~ 5.2 e Swift 5

Você pode estruturar seus dados de parâmetro

Trabalhar com API json falsa

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
fonte