如何在 swift 3 中将单个对象作为参数发布到 http 请求中

Posted

技术标签:

【中文标题】如何在 swift 3 中将单个对象作为参数发布到 http 请求中【英文标题】:how to post single object as parameter in http request in swift 3 【发布时间】:2018-04-11 14:43:33 【问题描述】:

我也测试了这个链接。给我不好的请求(400)

使用原生库而不是 almafire

这是我偷偷摸摸的链接 send object as parameter

请给我投票

这是我的完整代码

guard let url=URL(string: "http://test.com/google/getAddress") elsereturn

let parameters=GoogleMap()

var requst=URLRequest(url: url)
requst.httpMethod="POST"
requst.addValue("application/json", forHTTPHeaderField: "Content-Type")
requst.httpMethod="POST"
guard let httpbody=try? JSONSerialization.data(withJSONObject: parameters, options: []) elsereturn

requst.httpBody=httpbody

print(url)

let _=URLSession.shared.dataTask(with: requst)  (data, response, error) in
    if let data=data

        do
            let json=try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)

            print(json)
        
        catch

            print(error)
        
    
    .resume()
    

我的模型类

class Model 

    private var latitude:Double?
    private var longitude:Double?

    var _latitude:Double
        get
            return latitude!
        
        set
            latitude=newValue
        
    

    var _longitude:Double

        get
            return longitude!
        
        set
            longitude=newValue
        
    

    func toJSON() -> [String: Any] 
        return [ "latitude": latitude as Any, "longtide": longitude as Any]
    


我已经作为字典进行了测试,但服务器在其 JSON 响应中给了我“错误请求”错误。

【问题讨论】:

【参考方案1】:

主要问题是您的 JSON 为 longitude 使用了错误的密钥。您正在使用longtide,这显然不是您想要的。如果你使用longitude,它可以正常工作。


一些不相关的观察:

    您正在使用do-catch,但没有try。您正在使用try?,它不会抛出任何错误,而是在出现问题时返回nil。因此没什么可抓的。如果要捕获错误,请使用 try,而不是 try?

    您有一个奇怪的模型对象,其中您具有私有属性,但随后具有 getset 私有属性的计算属性。如果您没有在自定义 getter 和 setter 中做任何有价值的事情,那么您应该完全失去这些计算属性,因为这只是令人费解且效率低下。此外,下划线约定用于隐藏的私有属性,而不是您公开的属性。

    可以推断您的GoogleMap 方法正在返回由toJSON 生成的[String: Any]。在 Swift 4 中,您可以使用 JSONEncoder 并将模型对象设为 Encodable(或 Codable),您可以避免使用 toJSON 方法。只需更改 GoogleMap 以返回简单的模型对象,然后您可以使用 JSONEncoder 对其进行编码。

所以,这给我们留下了:

let url = URL(string: "http://test.com/google/getAddress")!

var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let coordinate = Coordinate(latitude: 34.05222, longitude: -118.242) // set this however you want
request.httpBody = try! JSONEncoder().encode(coordinate)

URLSession.shared.dataTask(with: request)  data, _, error in
    guard let data = data, error == nil else 
        print(error ?? "Unknown error")
        return
    

    do 
        let responseObject = try JSONSerialization.jsonObject(with: data)
        print(responseObject)
     catch let parseError 
        print(parseError)
    
.resume()

您的模型对象被简化为:

struct Coordinate: Codable 
    var latitude: Double
    var longitude: Double

或者,如果你真的需要它作为引用类型,class:

class Coordinate: Codable 
    var latitude: Double
    var longitude: Double

    init(latitude: Double, longitude: Double) 
        self.latitude = latitude
        self.longitude = longitude
    


如果你被 Swift 3 卡住了,那就继续做一本字典,但我会写成 [String: Double],例如

let url = URL(string: "http://ipinbar.net:8080/google/getAddress")!

var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let coordinate = Coordinate(latitude: 34.05222, longitude: -118.242) // set this however you want
request.httpBody = try! JSONSerialization.data(withJSONObject: coordinate.dictionary)

URLSession.shared.dataTask(with: request)  data, _, error in
    guard let data = data, error == nil else 
        print(error ?? "Unknown error")
        return
    

    do 
        let responseObject = try JSONSerialization.jsonObject(with: data)

        print(responseObject)
     catch let parseError 
        print(parseError)
    
.resume()

struct Coordinate 
    var latitude: Double
    var longitude: Double

    var dictionary: [String: Double]  return ["latitude": latitude, "longitude": longitude] 

【讨论】:

嘿,Rob.tnx 很多。我正在使用 swift 3,但我现在无法更新到 4。你能帮忙处理这行代码吗:request.httpBody = try! JSONEncoder().encode(坐标)。在swift 3 ??相当于JSONEncoder() @Ryan110 - 那么字典技巧很好,尽管生成的模型类型仍然比您提供的原始代码 sn-p 简单得多。 ;) 请参阅上面的扩展答案。 你成就了我的一天......!!所以你有一个问题:为什么 torsion() func 不起作用但 var dictionary 工作得很好。两者都有点相同? 和 tnx 给那些因为不合逻辑的原因投票给我的人 @Ryan110 - 很大程度上是因为,正如我在回答开头指出的那样,我使用了longitude,而您使用了longtide(您拼错了密钥的名称)。我认为将选项转换为 Any 而不打开它们是危险的,尽管我认为从技术上讲这不是问题。

以上是关于如何在 swift 3 中将单个对象作为参数发布到 http 请求中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 3 中使用 Alamofire 在 POST 请求中将给定的 JSON 作为参数发送?

在 Alamofire Swift 3 中将数组作为参数发送

可以在 Swift 中将枚举类型名称作为参数传递吗?

如何在 Swift 4 中将 Encodable 或 Decodable 作为参数传递?

在 Swift3 中将查询参数添加到 iOS 中的 GET url

如何在 Swift 中将单个数组转换为嵌套数组? [复制]