Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用变量键解析JSON_Json_Swift_Codable - Fatal编程技术网

使用变量键解析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 } ,或: 此外,我应该能够更改基础货币和要比较的货币,并更改要比较的货币数量。 我已经试过了 处理它的最佳方式是什么 谢谢 其他信息 因此,我在没有初始值

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

JSON示例:

{
"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"))
}