使用奇怪的 JSON 文件格式查找汇率键值
Posted
技术标签:
【中文标题】使用奇怪的 JSON 文件格式查找汇率键值【英文标题】:Exchange Rate Key Value Lookup With Weird JSON File Format 【发布时间】:2021-04-27 15:12:48 【问题描述】:在给定密钥(3 位货币代码)的情况下,我需要查找货币汇率方面的帮助。 JSON 对象非常不寻常,没有日期、时间戳、成功或速率等标签。第一个字符串值是基础货币或本国货币。在下面的示例中,它是“usd”(美元)。
我想通过给出其 3 位货币代码并将其存储在有序数组中来遍历所有货币以获取每种汇率。
"usd":
"aed": 4.420217,
"afn": 93.3213,
"all": 123.104693,
"amd": 628.026474,
"ang": 2.159569,
"aoa": 791.552347,
"ars": 111.887966,
"aud": 1.558363,
"awg": 2.164862,
"azn": 2.045728,
"bam": 1.9541,
"bbd": 2.429065,
"bch": 0.001278
在格式稍有不同的 JSON 对象中,我使用以下循环将汇率复制到有序数组。
for index in 0..<userData.rateArray.count
currencyCode = currCode[index]
if let unwrapped = results.rates[currencyCode]
userData.rateArray[index] = 1.0 / unwrapped
以下代码是用于获取 3 位货币代码和汇率的 API(通过 UpdateRates 调用)。
class GetCurrency: Codable
let id = UUID()
var getCurrencies: [String : [String: Double]] = [:]
required public init(from decoder: Decoder) throws
do
print(#function)
let baseContainer = try decoder.singleValueContainer()
let base = try baseContainer.decode([String : [String: Double]].self)
for key in base.keys
getCurrencies[key] = base[key]
catch
print(error)
throw error
class CurrencyViewModel: ObservableObject
@Published var results: GetCurrency?
@Published var selectedBaseCurrency: String = "usd"
func UpdateRates()
let baseUrl = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/"
let baseCur = selectedBaseCurrency // usd, eur, cad, etc
let requestType = ".json"
guard let url = URL(string: baseUrl + baseCur + requestType) else
print("Invalid URL")
return
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) data, response, error in
if let data = data
do
let decodedResponse = try JSONDecoder().decode(GetCurrency.self, from: data)
DispatchQueue.main.async
self.results = decodedResponse
// this prints out the complete table of currency code and exchange rates
print(self.results?.getCurrencies["usd"] ?? 0.0)
catch
//Error thrown by a try
print(error)//much more informative than error?.localizedDescription
if error != nil
//data task error
print(error!)
.resume()
【问题讨论】:
如果您已经拥有“usd”,self.results?.getCurrencies["usd"]?.keys
会在您将其放入循环时为您提供其余货币的 3 个字母代码/密钥。如果您将UpdateRates()
更改为func UpdateRates(baseCurrency: String)
以接收参数并将其更改为使用参数let baseCur = baseCurrency
,您可以在循环中调用UpdateRates(baseCurrency: key)
。
我在调用 UpdateRates: .onAppear(perform: vm.UpdateRates(baseCur: baseCurrency.baseCur.baseS)) 时遇到问题。它给出错误无法将类型“()”的值转换为预期的参数类型“(()-> Void)?”为了防止与我的基础货币结构混淆,我将传递给 UpdateRates 的参数更改为 baseCur。存储在结构体baseCurrency.baseCur和baseS中的系统基础货币是基础货币3位字符串。
您缺少一些括号,使 onAppear 方法类似于我在上一个问题中使用的方法。
好的,我让 onAppear 工作了;我看到它不需要 perform 关键字。在 UpdateRates 我可以打印(self.results?getCurrencies[baseCur]?.values ?? 0.0) 它给了我一个大表baseCur基础货币的汇率。那么如何使用 3 位货币代码迭代这些值以获得给定键的单个值?
你遍历键看看第一条评论
【参考方案1】:
感谢 lorem ipsum 的帮助。下面是更新的 ASI 逻辑,它使用键/值查找将汇率复制到 rateArray。
class CurrencyViewModel: ObservableObject
@Published var results: GetCurrency?
@Published var rateArray = [Double] ()
init()
if UserDefaults.standard.array(forKey: "rates") != nil
rateArray = UserDefaults.standard.array(forKey: "rates") as! [Double]
else
rateArray = [Double] (repeating: 0.0, count: 160)
UserDefaults.standard.set(self.rateArray, forKey: "rates")
func updateRates(baseCur: String)
...
DispatchQueue.main.async
self.results = decodedResponse
// loop through all available currencies
for index in 0..<currCode.count
currencyCode = currCode[index]
// spacial handling for base currency
if currencyCode == baseCur
self.rateArray[index] = 1.0000
else
let homeRate = self.results?.getCurrencies[baseCur]
// complement and save the exchange rate
if let unwrapped = homeRate?[currencyCode]
self.rateArray[index] = 1.0 / unwrapped
catch
//Error thrown by a try
print(error)//much more informative than error?.localizedDescription
if error != nil
//data task error
print(error!)
.resume()
【讨论】:
以上是关于使用奇怪的 JSON 文件格式查找汇率键值的主要内容,如果未能解决你的问题,请参考以下文章