Jak szybko wysłać żądanie POST do BODY


97

Próbuję szybko wysłać prośbę o wpis z ciałem za pomocą Alamofire.

moje ciało json wygląda tak:

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

Próbuję zrobić let listz NSDictionnary, które wygląda następująco:

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

a moja prośba z Alamofire wygląda następująco:

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

Żądanie zawiera błąd i uważam, że problem dotyczy listy słowników, ponieważ jeśli wyślę żądanie bez listy, działa dobrze, więc masz jakiś pomysł?


Wypróbowałem sugerowane rozwiązanie, ale mam ten sam 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)
    }


1
Dzięki za komentarz, ale zamieścić swoje warunkiem nie pomaga, a ja nie staram się przekazać ciąg jako ciała, można więc proszę dokładnie przeczytać post
Inaczej B.

@YasserB. Przekształć swój JSON w NSString (jest na to metoda), a następnie użyj linku @Bhavin?
Larme

@Larme byłoby bardzo pomocne, gdybyś podał przykład
Stranger B.

@Larme Wypróbowałem sugerowane rozwiązanie, ale mam ten sam problem, żądanie nie działa, chyba że usunę listę z ciała syna
Stranger B.

Odpowiedzi:


97

Jesteś blisko. Formatowanie słownika parametrów nie wygląda poprawnie. Powinieneś spróbować następujących rzeczy:

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

Mam nadzieję, że to rozwiązało problem. Jeśli tak się nie stanie, proszę o odpowiedź, a ja odpowiednio dostosuję moją odpowiedź.


Jak ustawić niektóre właściwości mojego JSON na null, ponieważ nie mogę przypisać nildo AnyObject?
Amp Tanawat

3
@JaseemAbbas sprawdź swoją wersję Alamofire, jeśli korzystasz z wersji 4.0 + sprawdź moją odpowiedź poniżej
Gianni Carlo

jak wysłać ten typ parametru w przypadku, gdy kodowanie to .urlEncoding
Pramod Shukla

1
Nie można przekonwertować wartości typu „Int” na oczekiwany typ wartości słownikowej „AnyObject”
myatmins

co zrobić, jeśli powiedzmy, że wartość parametru „Lista” ma około 1000 elementów listy?
Nishad Arora

175

Jeśli używasz Alamofire v4.0 +, to zaakceptowana odpowiedź wyglądałaby następująco:

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

6
Wspaniały! Zmień zaakceptowaną odpowiedź na tę, proszę! :) lub połącz z obecnym dla rozwiązań Alamofire 3 i 4.
Tom van Zummeren

1
Zgoda - jest to wyraźne stwierdzenie, JSONEncodingaby ujednoznacznić typ, który zrobił to za mnie.
Thomas Verbeek,

@Gianni Carlo Użyłem tego samego, co Twoja odpowiedź, ale w mojej odpowiedzi dotyczącej sukcesu otrzymuję błędy.
Ramakrishna

@Ramakrishna, który może być powiązany z interfejsem API, z którego korzystasz. Aby przeanalizować odpowiedź, której zwykle używam biblioteki SwiftyJSON, daj mi znać, jakie błędy otrzymujesz
Gianni Carlo

Dzięki za odpowiedź. Mam rozwiązanie.
Ramakrishna

34

Nie lubię którykolwiek z pozostałych odpowiedzi tak daleko (może z wyjątkiem jednego przez SwiftDeveloper), ponieważ albo wymagają deserializowania swoją JSON, tylko na to, aby zostać ponownie w odcinkach lub troska o strukturze samego JSON.

Prawidłowa odpowiedź została zamieszczona przez afrodiewa w innym pytaniu. Powinieneś iść i zagłosować.

Poniżej znajduje się tylko moja adaptacja, z drobnymi zmianami (głównie jawny zestaw znaków UTF-8).

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

Zgadzam się, że odpowiedź @ SwiftDeveloper jest lepsza i (moim zdaniem) pełniejsza niż „poprawna”, o której wspomniałeś. Ale spierałbym się o dwie kwestie. Po pierwsze, „poprawna odpowiedź”, o której wspominasz, ma wadę, która toJSONStringnie jest metodą natywną, więc jest to w zasadzie czarna skrzynka, którą musisz zaimplementować. Po drugie, odpowiedź, którą udzielisz, dostarcza zmiennej, jsonktóra zaczyna się jako łańcuch json, realistycznie nikt nie ma parametrów w ten sposób, chyba że konwertujesz i przechowujesz je lokalnie w ten sposób.
Gianni Carlo

@GianniCarlo 1) toJSONStringw mojej odpowiedzi nie ma, 2) „realistycznie nikt nie ma takich parametrów” - to wiele założeń; JSON może pochodzić z całkiem różnych części aplikacji, w ogóle niezwiązanych z wysyłaniem żądania, io których nic nie wie kod sieciowy.
Sea Coast of Tibet

Dzięki za ułatwienie mi życia !!! 1 Używam Alamofire z Flask Backend. Od Postmana wszystko działało dobrze, ale od Alamofire nie działa. Parametry treści HTTP i adresu URL oraz sposób ich ustawiania. Dzięki jeszcze raz.
Vineel

8

Xcode 8.X, Swift 3.X

Łatwa obsługa;

    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)

            }

7

Jeśli używasz, swift4a Alamofire v4.0akceptowany kod będzie wyglądał następująco:

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

6

Zaakceptowana odpowiedź w 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)
    }
}

WAŻNY! Użyj kodowania: JSONEncoding.default. Waliłem głową od godzin ... domyślnie kodowanie dla parametrów GET.
Reimond Hill

4

Lekko zredagowałem odpowiedź SwiftDeveloper , ponieważ nie działała dla mnie. Dodałem również walidację Alamofire.

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

1
Nadal działa w Alamofire 4.9.1 i Swift 5.1. Bardzo cenione
Abe

2

Jest kilka zmian, o których chciałbym powiadomić. Od teraz możesz uzyskać dostęp do żądania, JSON, błędu z obiektu odpowiedzi.

        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
        }

2

Alamofire Pobierz dane z POST, parametrem i nagłówkami

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

        }
    }

}

1

Oto jak utworzyłem żądanie Http POST ze swiftem, które wymaga parametrów z kodowaniem Json i nagłówkami.

Utworzono klienta API BKCAPIClient jako współdzieloną instancję, która będzie zawierać wszystkie typy żądań, takie jak POST, GET, PUT, DELETE itp.

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

Utworzono klasę Operation, która zawiera wszystkie dane potrzebne do konkretnego żądania, a także zawiera logikę parsowania wewnątrz bloku uzupełniania.

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
}

Wywołaj API w dowolnym kontrolerze widoku, w którym potrzebujemy tych danych

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

}}

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
}

1

Jeśli ktoś zastanawia się, jak postępować z modelami i innymi rzeczami, zobacz poniżej

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

0

Alamofire ~ 5.2 oraz Swift 5

Możesz ustrukturyzować dane parametrów

Pracuj z fałszywym interfejsem API JSON

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)
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.