Swift 的 jsonbin API 问题

jsonbin API problems with Swift

提问人:Ars_Codicis 提问时间:9/4/2023 最后编辑:HangarRashArs_Codicis 更新时间:9/4/2023 访问量:77

问:

我正在构建一个使用 Alamofire 与 jsonbin API 对话的小应用程序。他们的 API 文档介绍了使用 Python 在 Python 中广泛“放置”或“更新”JSON 文件数据。我正在努力在 Swift 5 中做到这一点。

我的问题是当我尝试使用 put 命令将数据发送到特定文件时。查看代码:

import AlamoFire

func sendData()
    {
        let headers: HTTPHeaders = [
            "Content-Type": "application/json",
            "X-Master-Key": "x-x-x-x-x-x-x-x",
            "X-Bin-Meta": "false"
        ]
        
        let queue = DispatchQueue(label: "com.app.name", qos: .background, attributes: .concurrent)
        
        do{
            
            var testData = [
            
                "title": "My Test Task",
                "date": "My Date",
                "complete": "Completion Status",
                "assignee": "Bob Jones"
            
            ]
            
            AF.request("https://api.jsonbin.io/v3/b/x-x-x-x-x-x-x", method: .put, parameters: testData, headers: headers).validate().responseJSON(queue: queue) { response in
                switch response.result {
                case .success(_):
                    print("Success!")
                case .failure(let error):
                    print(error)
                }
            }
        }
        catch
        {
            print("Error occured.")
        }

        
    }

我正在尝试发送一个简单的JSON结构。我收到的错误是这样的:

esponseValidationFailed(reason: Alamofire.AFError.ResponseValidationFailureReason.unacceptableStatusCode(code: 400))

他们的 API 文档说,错误 400 通常意味着:

  • 您需要将 Content-Type 设置为 application/json

  • 提供的 Bin ID 无效

  • Bin (JSON 数据) 不能为空

我已经验证了所有这些要求都是正确的。

以下是根据他们的文档运行的 Python 代码:

import requests
url = 'https://api.jsonbin.io/v3/b/x-x-x-x-x-x'
headers = {
  'Content-Type': 'application/json',
  'X-Master-Key': 'x-x-x-x-x-x-x'
}
data = {"sample": "Hello World"}

req = requests.put(url, json=data, headers=headers)
print(req.text)

我错过了什么吗?数据类型是否不同?Swift 变量与 Python 变量不同吗?如何使用 Swift 和 Alamofire 5 将数据“放入”RESTful API?testDatadata

谢谢!

python json swift alamofire alamofire5

评论

0赞 larsks 9/4/2023
(1)你看过回复的文字吗?我不熟悉 AlamoFire,但 API 通常会在错误响应中包含有用的信息,以帮助您识别问题。(2) 如果您以 postbin(或只是 )之类的东西而不是实际的 API 为目标,并将工作请求与非工作请求进行比较,该怎么办?nc
0赞 Ars_Codicis 9/4/2023
@larsks 响应文本与错误相同。
0赞 larsks 9/4/2023
好吧,我想剩下的(2)。
0赞 Larme 9/4/2023
在 & 之间添加。目前,它不是作为 JSON 发送的,而是作为 URL 编码发送的。您可以在 和 : 之间添加并查看输出。encoder: JSONParameterEncoder.default,parameters: testData,headers: headers.cURLDescription { print("JSONBIN curl: \($0)") }request()validate()request(...).cURLDescription { print("JSONBIN curl: \($0)") }.validate()

答:

1赞 Larme 9/4/2023 #1

您当前的参数不是以 JSON 格式发送的,而是以 URL 编码的格式发送的。

你可以使用 Alamofire 的 cURL 描述工具方法来查看它的发送方式:

AF.request("https://api.jsonbin.io/v3/b/x-x-x-x-x-x-x",
           method: .put,
           parameters: testData,
           headers: headers)
.cURLDescription { print("JSONBIN curl: \($0)") }
.validate()
.responseJSON(queue: queue) { response in
    switch response.result {
    case .success(_):
        print("Success!")
    case .failure(let error):
        print(error)
    }
}

你会得到:

JSONBIN curl: $ curl -v \
    -X PUT \
    -H "Accept-Language: fr-US;q=1.0" \
    -H "User-Agent: Alamofired/1.0 (ZzZ; build:1; iOS 16.4.0) Alamofire/5.4.0" \
    -H "Accept-Encoding: br;q=1.0, gzip;q=0.9, deflate;q=0.8" \
    -H "Content-Type: application/json" \
    -H "X-Bin-Meta: false" \
    -H "X-Master-Key: x-x-x-x-x-x-x-x" \
    -d "assignee=Bob%20Jones&complete=Completion%20Status&date=My%20Date&title=My%20Test%20Task" \
    "https://api.jsonbin.io/v3/b/x-x-x-x-x-x-x"

重要的部分是

-d "assignee=Bob%20Jones&complete=Completion%20Status&date=My%20Date&title=My%20Test%20Task"

因此,您需要告知将参数作为 JSON 发送:

AF.request("https://api.jsonbin.io/v3/b/x-x-x-x-x-x-x",
           method: .put,
           parameters: testData,
           encoder: JSONParameterEncoder.default,
           headers: headers)
.cURLDescription { print("JSONBIN curl: \($0)") }
.validate()
.responseJSON(queue: queue) { response in
    switch response.result {
    case .success(_):
        print("Success!")
    case .failure(let error):
        print(error)
    }
}

然后,cURL 输出参数行为:

-d "{\"date\":\"My Date\",\"title\":\"My Test Task\",\"complete\":\"Completion Status\",\"assignee\":\"Bob Jones\"}" \

与您的代码无关,但: 不需要 /,没有 ,如果真的有 ,建议打印 ,而不仅仅是 。但。docatchtryerrortryprint("Error occured.")print("Error occurred: \(error)")

此外,已弃用,取而代之的是 和 。如果您仍然想使用(内部调用),请使用并自己调用它。responseJSON()CodableresponseDecodable(of:)JSONSerializationresponseJSON()responseData()

评论

0赞 Ars_Codicis 9/4/2023
非常感谢你,我的朋友!这一成功信息从未如此甜蜜。