【问题标题】:Problem with POST request from swift frontend来自swift前端的POST请求问题
【发布时间】:2019-07-08 23:08:38
【问题描述】:

我正在尝试实现 Swift 前端,以便它可以将数据上传到数据库,该数据库是通过 Flask 用 Python 编写并利用 PostgreSQL。我用于发送 POST 请求的前端 Swift 代码目前如下,如果重要的话,它是在 View Controller 中编写的:

func PostData(){

        let parameters:[String: Any]=["latitude":  35.0094040,
                        "longitude": -85.3275640,
                        "tag": "this is my fancy tag",
                        "image":"icecream.jpg"]
        let jsonURLString="http://localhost/api/tags"
        guard let url=URL(string: jsonURLString) else{
            return
        }
        var request=URLRequest(url: url)
        request.httpMethod="POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        guard let httpBody=try? JSONSerialization.data(withJSONObject: parameters, options: [])  else{
            return
        }
        request.httpBody=httpBody
        let session=URLSession.shared
        session.dataTask(with: request) { (data, _, error) in


            if let data=data{
                do{
                    try JSONSerialization.jsonObject(with: data, options: [])  
                }catch{
                    print(error)
                }
            }
            }.resume()
    }

我接受post请求的后端代码如下:

@app.route('/api/tags',  methods=  ["GET",  "POST"])
def get_tags_api():
    if request.method == "POST":
        latitude  =  request.form.get("latitude")
        longitude  =  request.form.get("longitude")
        text  =  request.form.get("tag")
        image_  =  request.form.get("image", None)
        print (latitude)
        print (longitude)
        print (text) 
        print (image_)
        create_tags(latitude=latitude, longitude=longitude, text=text, image=image_)

当我尝试运行以下代码时,我最终收到了来自 Xcode 的以下错误消息:

Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

在后端,所有变量都打印为 None,并带有以下错误消息:

[SQL: INSERT INTO tags (text, longitude, latitude, image) VALUES (%(text)s, %(longitude)s, %(latitude)s, %(image)s) RETURNING tags.id]
[parameters: {'text': None, 'longitude': None, 'latitude': None, 'image': None}]
(Background on this error at: http://sqlalche.me/e/gkpj)

鉴于前端PostData函数运行时后端显示错误消息,请求肯定已经发送,但后端没有从请求中检测到任何数据,我不知道这是为什么。我不确定我在这里做错了什么。我对 Swift 比较陌生,而且我对 Flask 没有太多经验。请帮忙。

【问题讨论】:

    标签: ios json swift flask


    【解决方案1】:

    我认为你的代码是错误的。

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

    可以参考Alamofire - ParameterEncoding.swift

    【讨论】:

    • 我没有使用 Alamofire,所以我不确定参考是否相关
    【解决方案2】:

    我认为您需要在向服务器发出请求之前对数据进行编码。你可以试试这段代码:

    guard let jsonData=try? JSONSerialization.data(withJSONObject: parameters, options: [])  else {return}
    let jsonString = String(data: jsonData, encoding: .utf8)!;
    

    【讨论】:

    • jsonString 的用途是什么?我已经让 httpBody=try 守卫了? JSONSerialization.data(withJSONObject: parameters, options: []) else{return}。我不确定我应该把你在代码中写的那行放在哪里。
    【解决方案3】:

    例子:

    let parameters:[String: Any] = ["latitude":  35.0094040,
                                    "longitude": -85.3275640,
                                    "tag": "this is my fancy tag",
                                    "image":"icecream.jpg"]
    
    private func query(_ parameters: [String: Any]) -> String {
        var components: [(String, String)] = []
        for key in parameters.keys.sorted(by: <) {
            let value = parameters[key]!
            components.append((escape(key), escape("\(value)")))
        }
        return components.map { "\($0)=\($1)" }.joined(separator: "&")
    }
    
    public func escape(_ string: String) -> String {
          let generalDelimitersToEncode = ":#[]@"
          let subDelimitersToEncode = "!$&'()*+,;="
          var allowedCharacterSet = CharacterSet.urlQueryAllowed
          allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
          var escaped = ""
          if #available(iOS 8.3, *) {
             escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
          } else {
             let batchSize = 50
             var index = string.startIndex
             while index != string.endIndex {
                   let startIndex = index
                   let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
                   let range = startIndex..<endIndex
                   let substring = string[range]
                   escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? String(substring)
                   index = endIndex
             }
          }      
        return escaped
    }
    request.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
    

    【讨论】:

    • 这是一个有用的答案,但最好添加一些文本来解释问题所在以及解决问题的原因 - 即在 Python 代码中发送 JSON 和期望表单发布数据之间存在混淆。
    • 我试过代码。没用。返回同样的错误
    猜你喜欢
    • 2016-12-16
    • 2014-03-22
    • 1970-01-01
    • 2012-05-16
    • 2021-12-17
    • 1970-01-01
    • 2017-05-17
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多