使用奇怪的 JSON 文件格式进行汇率键值查找

Exchange Rate Key Value Lookup With Weird JSON File Format

我需要帮助查找货币汇率,给定一个密钥(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
           }
      }

以下代码是 API 用于获取 3 位货币代码和汇率(通过 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()
    }
}

感谢 lorem ipsum 的帮助。下面是更新后的 ASI 逻辑,它使用 key/value 查找将汇率复制到 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()
    }
}