Swift 如何进行正确的API调用?

Swift 如何进行正确的API调用?,swift,Swift,我正在尝试通过进行API调用来访问fixer.io。这是我第一次尝试这样做,但我没有得到想要的结果。我想从这个JSON文件中获取“速率”和“结果” { "success": true, "query": { "from": "GBP", "to": "JPY", "amount": 25 }, "info": { "timestamp": 1519328414, "rate": 148

我正在尝试通过进行API调用来访问fixer.io。这是我第一次尝试这样做,但我没有得到想要的结果。我想从这个JSON文件中获取“速率”和“结果”

{
    "success": true,
    "query": {
        "from": "GBP",
        "to": "JPY",
        "amount": 25
    },
    "info": {
        "timestamp": 1519328414,
        "rate": 148.972231
    },
    "historical": ""
    "date": "2018-02-22"
    "result": 3724.305775
}
我实现的方法就是这个,但是我不知道在进行这个API调用时如何检索“rate”和“result”

extension APIsRuler {
  func getExchangeRate(from: String, to: String, amount: String, callback: @escaping (Bool, ConversionResult?) -> Void) {
    var request = URLRequest(url: APIsRuler.exchangeURL)
    let body = "convert?access_key=\(APIsRuler.exchangeAPI)&from=\(from)&to=\(to)&amount=\(amount)"
    request.httpMethod = "GET"
    request.httpBody = body.data(using: .utf8)
    let session = URLSession(configuration: .default)

    task?.cancel()
    task = session.dataTask(with: request) { (data, response, error) in
      DispatchQueue.main.async {
        guard let data = data, error == nil else {
          return callback(false, nil)
        }
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
          return callback(false, nil)
        }
        guard let responseJSON = try? JSONDecoder().decode([String: Double].self, from: data),
          let rate = responseJSON["rate"],
          let result = responseJSON["result"] else {
            return callback(false, nil)
        }
        let conversionResult = ConversionResult(exchangeRate: rate, exchangeResult: result)
        callback(true, conversionResult)
      }
    }
    task?.resume()
  }
}

使用真实模型对象,如下所示:

struct Conversion: Codable {
    let success: Bool
    let query: Query
    let info: Info
    let historical, date: String
    let result: Double
}

struct Info: Codable {
    let timestamp: Int
    let rate: Double
}

struct Query: Codable {
    let from, to: String
    let amount: Int
}
并使用
JSONDecoder
将您的响应解析为:

do {
  let conversion = try JSONDecoder().decode(Conversion.self, from: data)
  let rate = conversion.info.rate
  let result = conversion.result
} catch { print(error) }

您正在混合两种不同的API

  • 使用
    JSONSerialization
    ,结果就是一个字典,您可以通过键和索引订阅获得值。并且必须对每种类型进行下沉,并考虑嵌套<代码>速率< /代码>值。

    guard let responseJSON = try? JSONSerialization.jsonObject(with: data) as? [String:Any],
          let info = responseJSON["info"] as? [String:Any],
          let rate = info["rate"] as? Double,
          let result = responseJSON["result"] as? Double else {
              return callback(false, nil)
    }
    let conversionResult = ConversionResult(exchangeRate: rate, exchangeResult: result)
    callback(true, conversionResult)
    
  • 或者使用
    JSONDecoder
    然后您必须创建结构,只有当根对象中的所有值都是
    Double
    时,才能对
    [String:Double]
    进行解码,这显然不是事实

    struct Root: Decodable {
        let info: Info
        let result: Double
    }
    
    struct Info: Decodable {
        let rate: Double
    }
    
    guard let responseJSON = try? JSONDecoder().decode(Root.self, from: data) else {
        return callback(false, nil)
    }
    let conversionResult = ConversionResult(exchangeRate: responseJSON.info.rate, exchangeResult: responseJSON.result)
    callback(true, conversionResult)
    

  • 代码只是一个保持语法的示例。实际上,在解码JSON时,强烈建议不要使用
    try?
    。始终
    捕获
    并处理错误

    do {
        let responseJSON = try JSONDecoder().decode(Root.self, from: data)
        let conversionResult = ConversionResult(exchangeRate: responseJSON.info.rate, exchangeResult: responseJSON.result)
       callback(true, conversionResult)
    } catch {
        print(error)
        return callback(false, nil)
    }
    

    let rate=responseJSON[“rate”],
    为零,这就是它失败的原因。如果你是新手,不要做
    guard let 1,let 2,let 3 else{}
    ,做
    guard let 1 else{}guard let 2 else{}
    。换句话说,在multiple lines guard中,您可以知道哪一个失败了,通过调试(断点、打印值),您可能会发现遗漏了什么。首先,如果您第一次这样做,我建议您使用Alamofire+SwiftyJSON库。0,如果在1之前没有安装CocoaPods,请安装Alamofire和SwiftyJSON[1]:[2]:[3]:@Dris我不同意。为什么是豆荚,为什么是阿拉莫菲尔,为什么是迅捷?基本上,
    URLSession
    对于这样一个简单的任务来说是非常好的,所有第三方JSON解析器都已经过时,而支持
    Codable
    协议完全忽略了真正的错误<代码>解码([String:Double]。self
    ,应该失败。它应该是
    [String:Any]
    。不要用
    try?
    使
    try
    静音。使用do/catch。对于Swift 4+,请阅读有关Codable的内容。