将CURL转换为Swift



我需要将Microsoft Azure Cloud的以下curl调用转换为Swift:

curl -X POST "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=zh-Hans&toScript=Latn" -H "Ocp-Apim-Subscription-Key: <client-secret>" -H "Content-Type: application/json; charset=UTF-8" -d "[{'Text':'Hello, what is your name?'}]"

我需要将curl的JSON调用转换为Swift。问题是我没有JSON调用的经验,也不知道如何包含头、主体和参数。所以我尝试了以下代码:


let apiKey = "..."
let location = "..."
class AzureManager {

static let shared = AzureManager()

func makeRequest(json: [String: Any], completion: @escaping (String)->()) {

guard let url = URL(string: "https://api.cognitive.microsofttranslator.com/translate"),
let payload = try? JSONSerialization.data(withJSONObject: json) else {
return
}

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue(apiKey, forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
request.addValue(location, forHTTPHeaderField: "Ocp-Apim-Subscription-Region")
request.addValue("application/json", forHTTPHeaderField: "Content-type")
request.addValue("NaiVVl3DEFG3jdE5DE1NFAA6EABC", forHTTPHeaderField: "X-ClientTraceId")
request.httpBody = payload
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else { completion("Error::(String(describing: error?.localizedDescription))"); return }
guard let data = data else { completion("Error::Empty data"); return }

let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]
if let json = json,
let choices = json["translations"] as? [String: Any],
let str = choices["text"] as? String {
completion (str)
} else {
completion("Error::nothing returned")
}

}.resume()
}
}

然后这样称呼它:

let jsonPayload = [
"api-version": "3.0",
"from": "en",
"to": "it",
"text": "Hello"
] as [String : Any]

AzureManager.shared.makeRequest(json: jsonPayload) { [weak self] (str) in
DispatchQueue.main.async {
print(str)
}
}

我得到的错误是:

Optional(["error": {
code = 400074;
message = "The body of the request is not valid JSON.";
}])

和:

错误::没有返回

以下是Microsoft Azure Translator的文档:https://learn.microsoft.com/de-de/azure/cognitive-services/translator/reference/v3-0-translate

让我们分析您的cURL command,让我们用换行符使其更具可读性。如果你想让它在Terminal.app中正常工作,只需在行的末尾添加

curl 
-X POST  
"https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=zh-Hans&toScript=Latn" 
-H "Ocp-Apim-Subscription-Key: <client-secret>"  
-H "Content-Type: application/json; charset=UTF-8"  
-d "[{'Text':'Hello, what is your name?'}]"

-H:用addValue(_,forHTTPHeaderField:)设置-d:用httpBody =设置长URL,即request.url

cURL命令和URLRequest模式之间有两个主要区别。

首先,您确实混合了有效载荷&URL设置。

url应该是"https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=zh-Hans&toScript=Latn",而不是"https://api.cognitive.microsofttranslator.com/translate",您将api-versiontotoScript(顺便说一句,缺少那个(放在httpBody中。将它们放入URL中。您可以使用URLQueryItem来正确格式化它们。请参阅相关问题。

现在,一旦你解决了这个问题,就会出现第二个问题:

[{'Text':'Hello, what is your name?'}],我将顺便介绍一个奇怪的事实,即它使用单引号,但是,这里JSON是顶级数组,而不是字典。此外,它是Text,而不是text(可能区分大小写(。

如果您想查看您在httpBody中发送的内容,请不要犹豫:

if let jsonStr = String(data: request.httpBody ?? Data(), encoding: .utf8) {
print("Stringified httpBody: (jsonStr)")
}

因此,请修复您的参数,直到它与正在工作的cURL命令中的on相匹配。如前所述,它是一个数组,而不是字典。

最后,避免使用try?,请正确使用do/try/catch,因为如果它失败了,至少你需要了解它。
如果你不希望在顶级使用JSON字符串,就不需要使用.allowFragments。给你一本字典
我建议现在在Swift 4+中使用Codable,而不是JSONSerialization

编辑:在查看文档时,当您混合参数/查询时,请记住:"查询参数";,这是针对URLQueryItems的,它在URL中。请求正文:这是针对httpBody的。

最新更新