如何将JSON结构转换为字典或结构

时间:2019-05-04 19:25:01

标签: json swift jagged-arrays

我正在提取不同货币的汇率。我有一个可行的解决方案,但似乎并不优雅。我使用JSON输入文件,并且想要将其转换为字典,因此可以轻松访问特定日期的货币汇率。

我的目标是在没有太多代码和灵活性的情况下拥有最佳方法。

它在Swift 5中,带有JSON输入文件。输入文件如下:

{
"terms":{
    "url": "https://www.banqueducanada.ca/conditions-utilisation-avis/"
},
"seriesDetail":{
"FXEURCAD":{"label":"EUR/CAD","description":"Taux de change quotidien de l’euro en dollars canadiens"},
"FXGBPCAD":{"label":"GBP/CAD","description":"Taux de change quotidien de la livre sterling en dollars canadiens"},
"FXMXNCAD":{"label":"MXN/CAD","description":"Taux de change quotidien du peso mexicain en dollars canadiens"},
"FXUSDCAD":{"label":"USD/CAD","description":"Taux de change quotidien du dollar américain en dollars canadiens"}
},
"observations":[
{"d":"2019-04-29","FXUSDCAD":{"v":1.3456}, "FXEURCAD":{"v":1.5029}, "FXGBPCAD":{"v":1.7391}, "FXMXNCAD":{"v":0.07083}},
{"d":"2019-04-30","FXUSDCAD":{"v":1.3423}, "FXEURCAD":{"v":1.5055}, "FXGBPCAD":{"v":1.7493}, "FXMXNCAD":{"v":0.07071}},
{"d":"2019-05-01","FXUSDCAD":{"v":1.3416}, "FXEURCAD":{"v":1.5070}, "FXGBPCAD":{"v":1.7540}, "FXMXNCAD":{"v":0.07105}},
{"d":"2019-05-02","FXUSDCAD":{"v":1.3462}, "FXEURCAD":{"v":1.5055}, "FXGBPCAD":{"v":1.7543}, "FXMXNCAD":{"v":0.07053}},
{"d":"2019-05-03","FXUSDCAD":{"v":1.3429}, "FXEURCAD":{"v":1.5021}, "FXGBPCAD":{"v":1.7611}, "FXMXNCAD":{"v":0.07069}}
]
}

我正在提取“观察”部分。

日期的货币列表可能会有所不同。它可以有更多或更少。我至少有一种货币。我希望有一种不需要手动编码不同汇率的解决方案。

func getCurrencies (){
    var currencies = [String : [String:Double]]()

    if let urlJSON = URL(string: "https://www.banqueducanada.ca/valet/observations/FXUSDCAD,FXEURCAD,FXGBPCAD,FXMXNCAD/json?recent=5"){
        do {
            let contents =  try String(contentsOf: urlJSON)
            print(contents)

            let data = Data(contents.utf8)

            if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
               let observations = json["observations"] as! [[String: Any]]
                for (x,part) in observations.enumerated() {
                    let date = part["d"] as! String
                    currencies [date] = [String:Double]()

                    // get the currencies in the JSON structure

                    currencies [date]!["FXEURCAD"] = (part["FXEURCAD"] as! [String : Double])["v"]
                    currencies [date]!["FXGBPCAD"] = (part["FXGBPCAD"] as! [String : Double])["v"]
                    currencies [date]!["FXMXNCAD"] = (part["FXMXNCAD"] as! [String : Double])["v"]
                    currencies [date]!["FXUSDCAD"] = (part["FXUSDCAD"] as! [String : Double])["v"]
                } // for
                print (currencies)
            } // if  let json
        } catch {}
    } // if
} // getCurrencies

生成的货币词典很好:

["2019-05-02": ["FXGBPCAD": 1.7543, "FXMXNCAD": 0.07053, "FXEURCAD": 1.5055, "FXUSDCAD": 1.3462], 
 "2019-05-01": ["FXGBPCAD": 1.754, "FXEURCAD": 1.507, "FXMXNCAD": 0.07105, "FXUSDCAD": 1.3416], 
 "2019-05-03": ["FXEURCAD": 1.5021, "FXUSDCAD": 1.3429, "FXMXNCAD": 0.07069, "FXGBPCAD": 1.7611], 
 "2019-04-30": ["FXEURCAD": 1.5055, "FXMXNCAD": 0.07071, "FXUSDCAD": 1.3423, "FXGBPCAD": 1.7493], 
 "2019-04-29": ["FXGBPCAD": 1.7391, "FXEURCAD": 1.5029, "FXUSDCAD": 1.3456, "FXMXNCAD": 0.07083]]

我可以使用该命令提取值:

   print (currencies ["2019-05-03"]!["FXUSDCAD"]!)

有更好的方法吗? JSONSerialization.jsonObject是正确的方法吗?

1 个答案:

答案 0 :(得分:0)

在这种情况下,JSONSerialization是一种合理的方法,但是永远不要从远程URL同步加载数据。

这是更通用的版本,带有用于货币的参数和异步网络请求。

func getCurrencies(_ currencies : [String]){
    var result = [String : [String:Double]]()

    if let urlJSON = URL(string: "https://www.banqueducanada.ca/valet/observations/" + currencies.joined(separator:",") + "/json?recent=5"){
        URLSession.shared.dataTask(with: urlJSON) { (data, _, error) in
            if let error = error { print(error); return }
            do {
                if let json = try JSONSerialization.jsonObject(with: data!) as? [String: Any] {
                    let observations = json["observations"] as! [[String: Any]]
                    for part in observations {
                        let date = part["d"] as! String
                        result[date] = [String:Double]()

                        // get the currencies in the JSON structure
                        for currency in currencies {
                            result[date]![currency] = (part[currency] as! [String : Double])["v"]
                        }
                    } // for
                    print(result)
                } // if  let json
            } catch {
                print(error)
            }
        }.resume()
    } // if
} // getC


getCurrencies(["FXUSDCAD","FXEURCAD","FXGBPCAD","FXMXNCAD"])