用可变键解析 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" 个您想要处理的对象。
我正在尝试使用包含动态键和动态数量的值的货币汇率来解析 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" 个您想要处理的对象。