用可变键解析 JSON

Parse JSON with variable keys

我正在尝试使用包含动态键和动态数量的值的货币汇率来解析 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
}

此外,我应该能够更改基础货币和要比较的货币,以及更改要比较的货币数量。 我已经试过了 .

最佳处理方式是什么?

谢谢

附加信息

所以,我创建了没有初始化器的结构

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

并尝试对其进行解码

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

我仍然遇到错误。

最终,我只需要一组货币汇率(值)来将其填充到 Table 视图中。

经过一些实验后,我的 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 添加条件扩展。然而,这会将您的新功能添加到 any Dictionary 匹配签名,这在许多情况下可能是可以接受的,即使它 'feels' 从设计角度来看是错误的。

如您所见,Swift 中有一大堆方法可以解决这个问题。我建议您使用 Codable 协议和一个附加密钥。很可能有 "other things" 个您想要处理的对象。