当密钥根据用户输入更改时,如何从json解码变量? [英] How to decode variable from json when key is changing according to user input?

查看:88
本文介绍了当密钥根据用户输入更改时,如何从json解码变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Swift 4中的JSONDecoder()解析来自 CoinmarketCap 的一些JSON响应.但是问题在于,json的响应会根据用户输入而发生变化.例如,如果用户想要以eur为单位的价格,则输出如下:

I am trying to parse some JSON response coming from CoinmarketCap using the JSONDecoder() in Swift 4. But the problem is that the response from json is changing according to user input. e.g if user wants the price in eur, the output is following:

[
    {
        "price_eur": "9022.9695444"
    }
]

但是如果用户想要以gbp为单位的价格:

but if user wants the price in gbp:

[
    {
        "price_gbp": "7906.8032145"
    }
]

所以问题是,如果变量(json键)的名称发生变化,我应该如何构造从Decodable继承的结构?

So the question is how should I make the struct that inherits from Decodable if the variable(json key) name is changing?

推荐答案

您可以通过为结构创建自定义的init(from:)方法,然后使用两组编码键(包含所有键的enum)来解码动态键在编译时是已知的,另外一个struct您可以使用通过用户输入(包含货币名称)生成的动态键进行初始化.

You can decode the dynamic key by creating a custom init(from:) method for your struct, then using two set of coding keys, an enum containing all keys that are known at compile time and another struct that you initialize using the dynamic keys that are generated using user input (contain the name of the currency).

在您的自定义init(from:)方法中,您只需要使用它们各自的键对每个属性进行解码即可.

In your custom init(from:) method you just need to decode each property using their respective keys.

let chosenCurrency = "gbp"

struct CurrencyResponse: Decodable {
    let name:String
    let symbol:String
    let price:String
    private static var priceKey:String {
        return "price_\(chosenCurrency)"
    }

    private enum SimpleCodingKeys: String, CodingKey {
        case name, symbol
    }

    private struct PriceCodingKey : CodingKey {
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }
        var intValue: Int?
        init?(intValue: Int) {
            return nil
        }
    }

    init(from decoder:Decoder) throws {
        let values = try decoder.container(keyedBy: SimpleCodingKeys.self)
        name = try values.decode(String.self, forKey: .name)
        symbol = try values.decode(String.self, forKey: .symbol)
        let priceValue = try decoder.container(keyedBy: PriceCodingKey.self)
        price = try priceValue.decode(String.self, forKey: PriceCodingKey(stringValue:CurrencyResponse.priceKey)!)
    }
}

do {
    let cryptoCurrencies = try JSONDecoder().decode([CurrencyResponse].self, from: priceJSON.data(using: .utf8)!)
} catch {
    print(error)
}

测试JSON:

let priceJSON = """
    [
    {
    "id": "bitcoin",
    "name": "Bitcoin",
    "symbol": "BTC",
    "rank": "1",
    "price_\(chosenCurrency)": "573.137",
    "price_btc": "1.0",
    "24h_volume_\(chosenCurrency)": "72855700.0",
    "market_cap_\(chosenCurrency)": "9080883500.0",
    "available_supply": "15844176.0",
    "total_supply": "15844176.0",
    "percent_change_1h": "0.04",
    "percent_change_24h": "-0.3",
    "percent_change_7d": "-0.57",
    "last_updated": "1472762067"
    },
    {
    "id": "ethereum",
    "name": "Ethereum",
    "symbol": "ETH",
    "rank": "2",
    "price_\(chosenCurrency)": "12.1844",
    "price_btc": "0.021262",
    "24h_volume_\(chosenCurrency)": "24085900.0",
    "market_cap_\(chosenCurrency)": "1018098455.0",
    "available_supply": "83557537.0",
    "total_supply": "83557537.0",
    "percent_change_1h": "-0.58",
    "percent_change_24h": "6.34",
    "percent_change_7d": "8.59",
    "last_updated": "1472762062"
}
]
"""

这篇关于当密钥根据用户输入更改时,如何从json解码变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆