我正在尝试实现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()
}
我用于接受帖子请求的后端代码如下:
@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没有太多的经验。请帮忙。
答案 0 :(得分:0)
我认为您的代码是错误的。
guard let httpBody=try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
答案 1 :(得分:0)
我认为您需要在请求服务器之前对数据进行编码。您可以尝试以下代码:
guard let jsonData=try? JSONSerialization.data(withJSONObject: parameters, options: []) else {return}
let jsonString = String(data: jsonData, encoding: .utf8)!;
答案 2 :(得分:0)
示例:
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)