使用变量键解析JSON
我试图用包含动态键和动态数量的值的货币率解析JSON。输出取决于输入参数,例如基础货币和要比较的几种货币 JSON示例:使用变量键解析JSON,json,swift,codable,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 } ,或: 此外,我应该能够更改基础货币和要比较的货币,并更改要比较的货币数量。 我已经试过了 处理它的最佳方式是什么 谢谢 其他信息 因此,我在没有初始值
{
"USD_AFN": 70.129997,
"USD_AUD": 1.284793,
"USD_BDT": 82.889999,
"USD_BRL": 3.418294,
"USD_KHR": 4004.99952
}
,或:
此外,我应该能够更改基础货币和要比较的货币,并更改要比较的货币数量。
我已经试过了
处理它的最佳方式是什么
谢谢
其他信息
因此,我在没有初始值设定项的情况下创建了结构
struct CurrencyRate: Codable {
var results : [String:Double]
}
并试图解码它
do { let results = try decoder.decode(CurrencyRate.self, from: dataToDecode) print(results) } catch { print("Error") }
我仍然得到错误
最后,我只需要一个货币汇率(值)数组来在表视图中填充它 经过一些实验后,我的游乐场看起来如下:
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
具有允许轻松扩展的优势。因为字典是结构体,所以不可能从中派生。如上一版本所示,可以将条件扩展添加到词典
。但是,这会将您的新函数添加到任何与签名匹配的字典中,这在许多情况下可能是可以接受的,即使从设计角度来看它“感觉”是错误的
正如你所看到的,在Swift中有很多方法可以解决这个问题。我建议您使用Codable
协议和附加密钥。最有可能的是,您需要对对象执行“其他操作”。我会保留字典(解码为[String:Double]
)我尝试使用此结构struct CurrencyRate:Codable{var results:[String:Double]init(results:[String:Double]){self results=results}
和让结果=尝试解码器.decode(CurrencyRate.self,from:dataToDecode)
,但它捕捉到一个错误。可能我的结构不适合这种情况?这是整个JSON吗?如果是,代码应该可以工作。你不需要结构中的初始值设定项,即使不符合Codable
是的,这是整个JSON,但它可能包含任意数量的对象和任意键的组合(XXX_XXX).因此,我在没有初始值设定项的情况下创建了结构struct CurrencyRate:Codable{var results:[String:Double]}
并尝试对其进行解码do{let results=try decoder.decode(CurrencyRate.self,from:dataToDecode)print(results)}catch{print(“Error”)}
我仍然得到错误。我做错了什么?在注释中放入多行代码是个坏主意。如果您喜欢这样做,请将其添加到问题中。您的JSON
缺少结果
键,这就是它无法解析的原因。目前您的JSON
是一个简单的哈希[字符串:Double]
即使使用JSONSerializer也可以解码。然而,你关于“最优”的问题暴露了一个(通常)问题:“你想(用它)做什么?”
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"))
}