Как сделать правильный вызов API? - PullRequest
0 голосов
/ 11 марта 2019

Я пытаюсь получить доступ к fixer.io с помощью вызова API.Это первый раз, когда я пытаюсь это сделать, но я не получаю желаемого результата.Я хотел бы получить "скорость" и "результат" из этого файла 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.

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()
  }
}

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Используйте реальный объект модели, например:

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) }
0 голосов
/ 11 марта 2019

Вы смешиваете два разных API.

  1. Либо используйте JSONSerialization, в результате получается словарь, и вы получаете значения по ключу и по подписке индекса. И вы должны преуменьшить каждый тип и учитывать вложенное значение rate.

    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)
    
  2. Или используйте JSONDecoder, тогда вам придется создавать структуры, декодирование до [String:Double] может работать, только если все значения в корневом объекте равны 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)
    

Код является лишь примером для сохранения вашего синтаксиса. Практически не рекомендуется использовать try? при декодировании JSON. Всегда catch и обрабатывать ошибки

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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...