如何在Swift中发送带有请求体的POST请求

117

我正在使用Alamofire在Swift中进行带有请求主体的POST请求。

我的JSON主体如下:

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

我正在尝试使用NSDictionary创建一个类似于let list的列表:

[[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
谢谢您的评论,但是您提供的帖子并没有帮助到我,而且我并不想将字符串作为正文传递,所以您能否仔细阅读帖子? - Stranger B.
@YasserB。将您的JSON转换为NSString(有相应的方法),然后使用@Bhavin提供的链接。 - Larme
@Larme 如果您提供一个例子将会非常有帮助。 - Stranger B.
@Larme 我已经尝试了建议的解决方案,但是我仍然有同样的问题,除非我从son body中删除列表,否则请求不起作用。 - Stranger B.
14个回答

197
如果您使用的是 Alamofire v4.0+,那么接受的答案应该如下所示:

如果您使用的是 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的解决方案。 - Tom van Zummeren
2
同意-对我来说,明确指定JSONEncoding来消除歧义的方式起到了作用。 - Thomas Verbeek
@GianniCarlo 先生,关于 Headers 参数怎么办?因为我的请求方法中有另一个名为“Headers”的参数。 - Ritesh.mlk
@Rishi,你可以将头文件添加为最后一个参数“headers”(在参数“encoding”之后),它接收一个“HTTPHeaders”,这基本上是一个字典String:String。 - Gianni Carlo
对我来说,这是因为encoding: JSONEncoding.default... 尝试了好几个小时... - Timeless
显示剩余5条评论

108

你很接近了。参数字典格式看起来不正确。你应该尝试以下方法:

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的某些属性设置为null,因为我无法将nil分配给AnyObject - Amp Tanawat
3
请检查您使用的Alamofire版本,如果您正在使用v4.0+版本,请查看下面我的回答。 - Gianni Carlo
如果编码方式是.urlEncoding,如何发送这种类型的参数 - Pramod Shukla
1
无法将类型为“Int”的值转换为预期的字典值类型“AnyObject”。 - Myat Min Soe
如果假设“List”参数的值有1000个列表元素,该怎么办? - Nishad Arora

49

到目前为止,除了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不是本地方法,因此它基本上是一个黑盒子,你必须自己实现。第二,你给出的答案提供了一个名为json的变量,它最初是一个json字符串,实际上没有人会以这种方式传递参数,除非你将它们转换并以这种方式存储。 - Gianni Carlo
@GianniCarlo 1) 我的答案中没有 toJSONString,2) "实际上没有人会这样传递参数" - 这是做出了很多假设;JSON 可以来自应用程序中完全不相关于发出请求的部分,并且网络代码一无所知。 - Sea Coast of Tibet
谢谢让我的生活变得更轻松了!我正在使用带有Flask后端的Alamofire。在Postman中一切都很顺利,但是从Alamofire中却不行。请问HTTP正文和URL参数应该如何设置?再次感谢。 - Vineel

19

接受的答案在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)
    }
}

3
重要提示!请使用编码方式:JSONEncoding.default。我已经苦思冥想数小时……默认编码为GET参数。 - Reimond Hill
1
参数类型“JSONEncoding”不符合预期类型“ParameterEncoder”。 - Takasur
1
@Takasur 使用JSONEncoding.default。 - Roger Nkosi
我曾经对生活失去了信心,但是你拯救了我。谢谢。 - Omar Masri
responseJSON已被弃用。 - Vinny

11

如果您正在使用swift4Alamofire 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)
                }
            }

只需在请求中添加[encoding: JSONEncoding.default]即可正确工作。 - M Hamayun zeb

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)

            }

6

Alamofire 5.5 和 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)
      }
  }
}

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


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

        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接