Як швидко надіслати запит POST із BODY


97

Я намагаюся зробити запит на публікацію зі швидким тілом за допомогою Alamofire.

моє тіло json виглядає так:

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

Я намагаюся зробити let listз NSDictionnary, які виглядають так:

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

і мій запит з використанням Alamofire виглядає так:

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

Запит має помилку, і я вважаю, що проблема в списку словників, тому що якщо я роблю запит без списку, він працює нормально, так що будь-яка ідея?


Я спробував запропоноване рішення, але я стикаюся з тією ж проблемою:

 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
Дякуємо за ваш коментар, але наданий вами допис не допомагає, і я не намагаюся передати рядок як тіло, тому, будь ласка, уважно прочитайте пост
Незнайомець Б.,

@YasserB. Перетворіть свій JSON у NSString (для цього існує метод), а потім скористайтеся посиланням @Bhavin?
Larme

@Larme було б дуже корисно, якщо ви наведете приклад
Незнайомець Б.

@Larme Я спробував запропоноване рішення, але у мене така сама проблема, і запит не працює, якщо не видалити список із тіла сина
Незнайка Б.

Відповіді:


97

Ви поруч. Форматування словника параметрів виглядає неправильно. Вам слід спробувати наступне:

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

Сподіваємось, це вирішило вашу проблему. Якщо цього не сталося, надішліть відповідь, і я відповідно скоригую свою відповідь.


Як встановити деякий властивість мого JSON в нуль, так як я не можу призначити nilдля AnyObject?
Amp Tanawat

3
@JaseemAbbas перевірте свою версію Alamofire, якщо ви користуєтесь версією 4.0 +, перегляньте мою відповідь нижче
Джанні Карло,

як надіслати цей тип параметра у випадку, якщо кодування є .urlEncoding
Шукла

1
Не вдається перетворити значення типу "Int" у очікуваний тип значення словника "AnyObject"
myatmins

як це зробити, якщо, скажімо, значення параметра "List" має приблизно 1000 елементів списку?
Нішад Арора

175

Якщо ви використовуєте Alamofire v4.0 +, прийнята відповідь буде виглядати так:

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
Чудово! Змініть прийняту відповідь на цю, будь ласка! :) або поєднати з поточним для рішень Alamofire 3 і 4.
Том ван Цуммерен,

1
Погоджено - це явна заява про JSONEncodingнеоднозначність типу, який це зробив для мене.
Thomas Verbeek,

@Gianni Carlo Я використовував те саме, що і ваша відповідь, але у відповіді на успіх я отримую помилки.
Рамакрішна,

@Ramakrishna, які можуть бути пов’язані з API, який ви споживаєте. Щоб проаналізувати відповідь, я зазвичай використовую бібліотеку SwiftyJSON, дайте мені знати, які помилки ви отримуєте
Джанні Карло,

Спасибі за Вашу відповідь. Я отримав рішення.
Рамакрішна,

34

Наразі мені не подобається жодна інша відповідь (за винятком, можливо, тієї SwiftDeveloper), оскільки вони або вимагають від вас десериалізації JSON, лише для його повторної серіалізації, або піклування про структуру самого JSON.

Правильну відповідь опублікував afrodev в іншому питанні. Ви повинні піти і проголосувати за це.

Нижче наведено лише мою адаптацію, з деякими незначними змінами (насамперед явна кодировка 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)
}

Я погоджуюсь, що відповідь @ SwiftDeveloper є кращою і (на мій погляд) повнішою, ніж "правильна", про яку ви згадали. Але я б аргументував два моменти. По-перше, що "правильна відповідь", яку ви згадали, має недолік, який toJSONStringне є власним методом, тому в основному це чорний ящик, який вам доведеться реалізувати. По-друге, відповідь, яку ви даєте, надає var, jsonякий починається як рядок json, реально ніхто не має параметрів таким чином, якщо ви не конвертуєте та не зберігаєте їх локально таким чином.
Джанні Карло

@GianniCarlo 1) toJSONStringу моїй відповіді немає, 2) "насправді ніхто не має таких параметрів" - це робить багато припущень; JSON може надходити з досить різних частин програми, взагалі не пов’язаних із поданням запиту, і про мережевий код нічого не відомо.
Морське узбережжя Тибету

Дякуємо, що полегшили мені життя !!! 1 Я використовую Alamofire з Flask Backend. У Поштаря все працювало добре, але у Alamofire це не працює. Параметри тіла та URL-адреси HTTP та способи їх встановлення. Знову дякую.
Vineel

8

Xcode 8.X, Swift 3.X

Простота використання;

    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

Якщо ви використовуєте swift4і Alamofire v4.0тоді прийнятий код буде виглядати так:

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

5

Прийнята відповідь у 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)
    }
}

4

Я трохи відредагував відповідь SwiftDeveloper , оскільки вона не працювала для мене. Я також додав перевірку 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
Все ще працює в Alamofire 4.9.1 та Swift 5.1. Дуже вдячний
Абе

2

Є кілька змін, про які я хотів би повідомити. Відтепер ви можете отримати доступ до запиту, JSON, помилки в об'єкті відповіді.

        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 за допомогою POST, параметра та заголовків

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

Ось як я створив запит Http POST із swift, який потребує параметрів із кодуванням Json та із заголовками.

Створений клієнт API BKCAPIClient як спільний екземпляр, який включатиме всі типи запитів, такі як POST, GET, PUT, DELETE тощо.

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

Створений клас Operation, який містить усі дані, необхідні для конкретного запиту, а також містить логіку розбору всередині блоку завершення.

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
}

Виклик API у будь-якому контролері перегляду, де нам потрібні ці дані

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

Якщо хтось цікавиться, як діяти з моделями та іншим, дивіться нижче

        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 та Swift 5

Ви можете структурувати дані параметрів

Робота з підробленим 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)
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.