Я прочитал Как декодировать вложенную структуру JSON с протоколом Swift Decodable? Это не относится к моему конкретному случаю использования, когда в качестве корневых словарей используются строковые литералы.
Также Как декодировать вложенную структуру JSON по протоколу Swift Decodable? ответ от Imanou Petit. Невозможно декодировать данные JSON из API. ответ от Лео Дабуса.
Валюты - это сами словари, представленные литеральными строковыми числами внутри словаря data
, так что это отбрасывает меня.Я ищу самую модель Swifty 4, использующую перечисления, где легко увидеть, какие контейнеры соответствуют каким словарям.
ps Дэвид Берри дал отличный ответ, который я реализовал ниже.Если у кого-то есть другие подходы к тому же результату, я бы хотел увидеть другие предложения.Возможно, есть более новые методы 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
}
}