使用变量键

时间:2018-04-16 19:36:15

标签: json swift codable

我试图用货币汇率解析JSON包含动态键和动态数量的值。输出取决于输入参数,例如基础货币和要比较的几种货币。

JSON示例:

{
"USD_AFN": 70.129997,
"USD_AUD": 1.284793,
"USD_BDT": 82.889999,
"USD_BRL": 3.418294,
"USD_KHR": 4004.99952
}

,或:

{
"EUR_CAD": 0.799997
}

此外,我应该能够更改基础货币和货币进行比较,并更改要比较的货币数量。 我已经尝试了answer

处理它的最佳方法是什么?

由于

其他信息

所以,我在没有初始化器的情况下制作了结构

struct CurrencyRate: Codable { 
var results : [String:Double] 
} 

并尝试解码

 do { let results = try decoder.decode(CurrencyRate.self, from: dataToDecode) print(results) } catch { print("Error") }

我仍然收到错误。

最终,我只需要一组货币汇率(值)来填充表格视图。

1 个答案:

答案 0 :(得分:0)

经过一些实验,我的Playground看起来如下:

import Cocoa
import Foundation

let jsonData = """
{
"USD_AFN": 70.129997,
"USD_AUD": 1.284793,
"USD_BDT": 82.889999,
"USD_BRL": 3.418294,
"USD_KHR": 4004.99952
}
""".data(using: .utf8)!

do {
    let obj = try JSONSerialization.jsonObject(with:jsonData, options:[])
    print(obj)          // this is an NSDictionary
    if let dict = obj as? [String:Double] {
        print(dict)     // This is not "just" a cast ... more than I thought
    }
}

struct CurrencyRate: Codable {
    var results : [String:Double]
}

// If you use a "results"-key it _must_ be present in your JSON, but it would allow to add methods
let resultsJson = """
{
  "results" : {
    "USD_AFN": 70.129997,
    "USD_AUD": 1.284793,
    "USD_BDT": 82.889999,
    "USD_BRL": 3.418294,
    "USD_KHR": 4004.99952
    }
}
""".data(using: .utf8)!

do {
    let currencyRate = try JSONDecoder().decode(CurrencyRate.self, from: resultsJson)
    print(currencyRate)
}

// this is probably the easiest solution for just reading it
do {
    let rates = try JSONDecoder().decode([String:Double].self, from:jsonData)
    print(rates)
}

// While you could do the following it does not feel "proper"
typealias CurrencyRatesDict = [String:Double]

extension Dictionary where Key == String, Value == Double {
    func conversionRate(from:String, to:String) -> Double {
        let key = "\(from)_\(to)"
        if let rate = self[key] {
            return rate
        } else {
            return -1.0
        }
    }
}

do {
    let currRates = try JSONDecoder().decode(CurrencyRatesDict.self, from:jsonData)
    print(currRates)
    print(currRates.conversionRate(from:"USD", to:"AUD"))
}

这教会了我一些东西。我不会认为NSDictionary(由JSONSerialization.jsonObject自动生成并且没有类型)可以轻松地将其转换为[String:Double],但当然可能会失败,您应该写一些错误处理以捕获它。

您的CurrencyRate struct有利于轻松扩展。由于字典是structs,因此不可能从它们派生。正如最后一个版本所示,可以向Dictionary添加条件扩展。但是,这会将您的新功能添加到符合签名的任何 Dictionary,这在许多情况下可能是可以接受的,即使它感觉'从设计角度看是错误的。

正如您所看到的,在Swift中有很多方法可以解决这个问题。我建议你使用Codable协议和一个额外的密钥。最有可能的是"其他的东西"你会想要用你的对象。