Если массив в JSON находится на уровне root, то код прост и красив:
JSONDecoder().decode([T].self, data)
Но как это работает под капотом?
Я хочу знать это для реализации пользовательского декодера ( с тем же стилем вызова ) в случае, когда массив не находится на уровне root.
Например:
{
"status": "success",
"data": {
"base": {
"symbol": "USD",
"sign": "$"
},
"coins": [
{
"name": "Bitcoin",
"price": 7783.1949110647,
},
{
"name": "Ethereum",
"price": 198.4835955777,
},
{
"name": "Tether",
"price": 1.0026682789,
},
{
"name": "Litecoin",
"price": 45.9617330332,
}
]
}
}
struct Coin: Decodable {
let name: String
let price: Double
init(from decoder: Decoder) throws {
let rootContainer = try decoder.container(keyedBy: CodingKeys.self)
let nestedContainer = try rootContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
var unkeyedContainer = try nestedContainer.nestedUnkeyedContainer(forKey: .coins)
let coinContainer = try unkeyedContainer.nestedContainer(keyedBy: CodingKeys.self)
name = try coinContainer.decode(String.self, forKey: .name)
price = try coinContainer.decode(Double.self, forKey: .price)
}
enum CodingKeys: String, CodingKey {
case data
case coins
case name
case price
}
}
Это почти работает!
Когда .decode(Coin.self, data)
возвращает только один, самый первый элемент в массиве.
Когда .decode([Coin].self, data)
, к сожалению, но выдает ошибку:
Ожидается декодировать массив, но вместо этого нашел словарь.
Похоже, я пропустил какой-то последний шаг, чтобы заставить его работать так, как я хочу.