我已经阅读了如何使用Swift Decodable协议解码嵌套的JSON结构?它没有解决我将字符串文字数字值用作根字典的特定用例。
另外,如何使用Swift Decodable协议解码嵌套的JSON结构?Imanou Petit的回答。无法从Leo Dabus的API答复中解码JSON数据。
货币本身就是字典,由字典内的文字字符串数字表示,data
因此这让我大吃一惊。我正在寻找使用枚举的最Swifty 4模型,在该模型中很容易看出哪些容器对应哪些字典。
ps大卫·贝里(David Berry)给出了一个很好的答案,下面我已经实现了。如果其他人有其他方法来获得相同的结果,我希望看到不同的建议。也许有一些尚不为人所知的更新的Swift 4方法或其他设计模式。
码
struct RawServerResponse {
enum RootKeys: String, CodingKey {
case data
case btc = "1"
case eth = "1027"
case iota = "1720"
case ripple = "52"
case neo = "1376"
case quotes
case USD
}
enum BaseKeys: String, CodingKey {
case id, name, symbol, maxSupply = "max_supply"
}
enum QuotesKeys: String, CodingKey {
case USD
}
enum USDKeys: String, CodingKey {
case price, marketCap = "market_cap"
}
let data: String
let id: Int
let name: String
let symbol: String
let maxSupply: Double
let price: Double
let marketCap: Double
}
extension RawServerResponse: Decodable {
init(from decoder: Decoder) throws {
// data
let container = try decoder.container(keyedBy: RootKeys.self)
data = try container.decode(String.self, forKey: .data)
// id
let idContainer = try container.nestedContainer(keyedBy: BaseKeys.self, forKey: .data)
id = try idContainer.decode(Int.self, forKey: .id)
// price
let priceContainer = try container.nestedContainer(keyedBy: USDKeys.self, forKey: .USD)
price = try priceContainer.decode(Double.self, forKey: .price)
}
}
API / JSON https://api.coinmarketcap.com/v2/ticker/
{
"data": {
"1": {
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"website_slug": "bitcoin",
"rank": 1,
"circulating_supply": 17041575.0,
"total_supply": 17041575.0,
"max_supply": 21000000.0,
"quotes": {
"USD": {
"price": 8214.7,
"volume_24h": 5473430000.0,
"market_cap": 139991426153.0,
"percent_change_1h": 0.09,
"percent_change_24h": 2.29,
"percent_change_7d": -2.44
}
},
"last_updated": 1526699671
},
"1027": {
"id": 1027,
"name": "Ethereum",
"symbol": "ETH",
"website_slug": "ethereum",
"rank": 2,
"circulating_supply": 99524121.0,
"total_supply": 99524121.0,
"max_supply": null,
"quotes": {
"USD": {
"price": 689.891,
"volume_24h": 2166100000.0,
"market_cap": 68660795252.0,
"percent_change_1h": 0.13,
"percent_change_24h": 2.51,
"percent_change_7d": 2.54
}
},
"last_updated": 1526699662
}
}
我将采用一种更简单的方法来处理数据,将“数据”视为键化的,相同的响应的集合,同样,“引号”是行情的键控集合。
struct RawServerResponse : Decodable {
enum Keys : String, CodingKey {
case data = "data"
}
let data : [String:Base]
}
struct Base : Decodable {
enum CodingKeys : String, CodingKey {
case id = "id"
case name = "name"
case symbol = "symbol"
case maxSupply = "max_supply"
case quotes = "quotes"
}
let id : Int64
let name : String
let symbol : String
let maxSupply : Double?
let quotes : [String:Quote]
}
struct Quote : Decodable {
enum CodingKeys : String, CodingKey {
case price = "price"
case marketCap = "market_cap"
}
let price : Double
let marketCap : Double
}
然后,如果您确实确实需要从那些更简单的结构中访问各个键值,则可以提供计算的访问器:
extension RawServerResponse {
enum BaseKeys : String {
case btc = "1"
case eth = "1027"
}
var eth : Base? { return data[BaseKeys.eth.rawValue] }
var btc : Base? { return data[BaseKeys.btc.rawValue] }
}
并且,同样可以为货币创建类似的访问器:
extension Base {
enum Currencies : String {
case usd = "USD"
}
var usd : Quote? { return quotes[Currencies.usd.rawValue]}
}
一旦您解决了该部分,那么原始问题中的此链接将向您显示如果需要的话如何展平结构。从本质上讲,它可以归结为将计算出的属性更改为let
要在构造函数中设置的属性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句