【问题标题】:(iOS / Swift) Simple Post Request with Key-Value Failed, But Succeeded using Postman(iOS / Swift) 键值对的简单发布请求失败,但使用 Postman 成功
【发布时间】:2019-10-28 07:39:21
【问题描述】:

我使用 Postman 创建了一个简单的 POST 请求,它成功了。这是正文和回复的截图

body and response

这是 Postman 中的标题截图

header

现在我正在使用 Swift 在 iOS 应用程序中创建一个 POST 请求。这是代码:

public func getResultItem(url: URL, _ completion:@escaping (ResultItem?, Error?) -> Void){
    let parameter = ["uname":"21120113120038", "pass":"123456"]

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
    guard let httpBody = try? JSONSerialization.data(withJSONObject: parameter, options: []) else {return}
    request.httpBody = httpBody

    URLSession.shared.dataTask(with: request) { (data, response, error) in
        var resultItem: ResultItem?

        guard let data = data else {
            completion(resultItem, error)
            return
        }

        do {
            resultItem = try JSONDecoder().decode(ResultItem.self, from: data)
            completion(resultItem, error)
        } catch let error as NSError{
            completion(resultItem, error)
        }
    }.resume()
}

问题是,来自 dataTask 完成处理程序的“数据”总是 0 字节。看起来我的请求无效,所以它没有返回 JSON。由于数据是 0 字节,所以“do”块在解码 JSON 时总是失败,并转向“catch”块。这里“catch”块中的error.description是->'给定的数据不是有效的JSON'。

我的代码的哪一部分是错误的?我的第一个假设是请求有问题。可能是参数或者httpbody请求错误,不知道怎么解决。

谢谢

【问题讨论】:

  • @Paulw11 您提供的链接中的代码与我的几乎相同
  • 是的,差不多。您会注意到您应该将 application/json 指定为内容类型
  • 这个我也试过了,还是不行

标签: ios swift httprequest httpresponse


【解决方案1】:

您的内容类型是application/x-www-form-urlencoded,但您将正文设置为 JSON 而不是 URL 编码的参数。您的 HTTP 正文与您现在的样子类似:

{"uname":"21120113120038","pass":"123456"}

...但你希望它看起来像这样:

uname=21120113120038&pass=123456

所以,替换这一行:

guard let httpBody = try? JSONSerialization.data(withJSONObject: parameter, options: []) else {return}

...用这样的东西:

guard let httpBody = parameter.map({
    [$0.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? "",
     $1.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? ""].joined(separator: "=")
}).joined(separator: "&").data(using: .utf8) else { return }

(不过,我觉得这有点乱,所以这里有一些扩展来清理它:)

extension String {
    var urlEncodedQueryKeyOrValue: String {
        return addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? ""
    }
}

extension Dictionary where Key == String, Value == String {
    var wwwFormURLEncodedString: String {
        return map { "\($0.urlEncodedQueryKeyOrValue)=\($1.urlEncodedQueryKeyOrValue)" }.joined(separator: "&")
    }
}

然后你会像这样使用它:

[...]
guard let httpBody = parameter.wwwFormURLEncodedString.data(using: .utf8) else { return }
request.httpBody = httpBody
[...]

【讨论】:

    猜你喜欢
    • 2018-11-12
    • 2018-06-05
    • 1970-01-01
    • 2022-09-30
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 2020-08-28
    相关资源
    最近更新 更多