#ios #json #swift #struct
#iOS #json #swift #структура
Вопрос:
В настоящее время я работаю с API финансового рынка, где я могу получать данные JSON в виде одного биржевого тикера / котировки или в пакете.
Я могу декодировать данные JSON, если я знаю, какой биржевой тикер я пытаюсь запросить у API заранее.
С чем я борюсь, так это с тем, как написать my structs
, чтобы я мог декодировать любой биржевой тикер, выбранный пользователем.
Например, при разработке я знаю, что захочу запросить исходные данные в AAPL, поэтому я напишу соответствующие struct
(ниже), но, скажем, при фактическом развертывании я захочу взглянуть на исходные данные TSLA, в таком случае у меня не было бы соответствующего TSLA struct
, написанного, потому что у меня есть только struct
запись для AAPL, поэтому я получаю сообщение об ошибке.
Есть ли какой-нибудь способ написать какую-то динамическую struct
или использовать библиотеку Swift, которая может помочь решить эту проблему?
Я опубликую фрагмент данных JSON и мой struct
ниже.
{"AAPL":
{"quote":
{"symbol":"AAPL",
"companyName":"Apple, Inc.",
"primaryExchange":"NASDAQ",
"calculationPrice":"close",
"open":112.67,
"openTime":1600781401038,
"openSource":"official",
"close":111.81,
"closeTime":1600804800589,
"closeSource":"official",
"high":112.86,
"highTime":1600819199980,
"highSource":"15 minute delayed price",
"low":109.16,
"lowTime":1600786957213,
"lowSource":"15 minute delayed price",
"latestPrice":111.81,
"latestSource":"Close",
"latestTime":"September 22, 2020",
"latestUpdate":1600804800589,
"latestVolume":183055373,
"iexRealtimePrice":111.545,
"iexRealtimeSize":56,
"iexLastUpdated":1600806216383,
"delayedPrice":110.6,
"delayedPriceTime":1600819199980,
"oddLotDelayedPrice":127.67,
"oddLotDelayedPriceTime":1600807552123,
"extendedPrice":110.6,
"extendedChange":-1.21,
"extendedChangePercent":-0.01082,
"extendedPriceTime":1600819199980,
"previousClose":110.08,
"previousVolume":195713815,
"change":1.73,
"changePercent":0.01572,
"volume":183055373,
"iexMarketPercent":0.007153872636301017,
"iexVolume":1303096,
"avgTotalVolume":196415720,
"iexBidPrice":0,
"iexBidSize":0,
"iexAskPrice":0,
"iexAskSize":0,
"iexOpen":null,
"iexOpenTime":null,
"iexClose":111.8,
"iexCloseTime":1600804792007,
"marketCap":1938483513000,
"peRatio":33.69,
"week52High":137.98,
"week52Low":53.15,
"ytdChange":0.50212,
"lastTradeTime":1600804799962,
"isUSMarketOpen":false
}
},
"FB":
{"quote":
{"symbol":"FB",
"companyName":"Facebook, Inc.",
"primaryExchange":"NASDAQ",
"calculationPrice":"close",
"open":253.31,
"openTime":1600781400128,
"openSource":"official",
"close":254.75,
"closeTime":1600804800789,
"closeSource":"official",
"high":255.32,
"highTime":1600819191691,
"highSource":"15 minute delayed price",
"low":248.22,
"lowTime":1600787261157,
"lowSource":"15 minute delayed price",
"latestPrice":254.75,
"latestSource":"Close",
"latestTime":"September 22, 2020",
"latestUpdate":1600804800789,
"latestVolume":30401995,
"iexRealtimePrice":254.695,
"iexRealtimeSize":100,
"iexLastUpdated":1600804797803,
"delayedPrice":253.8,
"delayedPriceTime":1600819191691,
"oddLotDelayedPrice":254.74,
"oddLotDelayedPriceTime":1600804799413,
"extendedPrice":253.8,
"extendedChange":-0.95,
"extendedChangePercent":-0.00373,
"extendedPriceTime":1600819191691,
"previousClose":248.15,
"previousVolume":24709378,
"change":6.6,
"changePercent":0.0266,
"volume":30401995,
"iexMarketPercent":0.025296103101128724,
"iexVolume":769052,
"avgTotalVolume":25154911,
"iexBidPrice":0,
"iexBidSize":0,
"iexAskPrice":0,
"iexAskSize":0,
"iexOpen":null,
"iexOpenTime":null,
"iexClose":254.695,
"iexCloseTime":1600804797803,
"marketCap":725735292113,
"peRatio":30.89,
"week52High":304.67,
"week52Low":137.1,
"ytdChange":0.241301,
"lastTradeTime":1600804800789,
"isUSMarketOpen":false}
}
}
----
struct iexTicker: Decodable {
let AAPL: iexQuote
let FB: iexQuote
}
struct iexQuote: Decodable {
let quote: iexData
}
struct iexData: Decodable {
let symbol: String?
let companyName: String?
let primaryExchange: String?
let calculationPrice: String?
let open: Double?
let openTime: Double?
let openSource: String?
let close: Double?
let closeTime: Double?
let closeSource: String?
let high: Double?
let highTime: Double?
let low: Double?
let lowTime: Double?
let lowSource: String?
let latestPrice: Double?
let latestSource: String?
let latestTime: String?
let latestUpdate: Double?
let latestVolume: Double?
let iexRealtimePrice: Double?
let iexRealtimeSize: Double?
let iexLastUpdated: Double?
let delayedPrice: Double?
let delayedPriceTime: Double?
let oddLotDelayedPrice: Double?
let oddLotDelayedPriceTime: Double?
let extendedPrice: Double?
let extendedChange: Double?
let extendedChangePercent: Double?
let extendedPriceTime: Double?
let previousClose: Double?
let previousVolume: Double?
let change: Double?
let changePercent: Double?
let volume: Double?
let iexMarketPercent: Double?
let iexVolume: Double?
let avgTotalVolume: Double?
let iexBidPrice: Double?
let iexBidSize: Double?
let iexAskPrice: Double?
let iexAskSize: Double?
let iexOpen: Double?
let iexOpenTime: Double?
let iexClose: Double?
let iexCloseTime: Double?
let marketCap: Double?
let peRatio: Double?
let week52High: Double?
let week52Low: Double?
let ytdChange: Double?
let lastTradeTime: Double?
let isUSMarketOpen: Bool?
}
Комментарии:
1. Разве структуры для AAPL и TSLA не одинаковы? Похоже, вам просто нужно расшифровать словарь типа
[TickerName: IEXQuote]
(гдеTickerName
просто псевдоним дляString
)2. Я думаю, вам не хватает некоторых частей вашего
JSON
. Я подозреваю, что начало должно быть{ "APPL": {"quote": {"symbol":"AAPL", ... } }, "FB": { ... }
, и вы оставили начальную{ "APPL":
часть.
Ответ №1:
Есть ли какой-нибудь способ написать какую-то динамическую структуру
Нет. Но вы можете написать другую структуру для каждого типа JSON, а затем преобразовать данные в какой-нибудь более универсальный тип. Например, если у вас есть две структуры, Ticker1Data и Ticker2Data, тогда у вас может быть перечисление AnyTicker
, чьи случаи имеют в качестве связанных типов Ticker1Data и Ticker2Data:
enum AnyTicker {
case ticker1(Ticker1Data)
case ticker2(Ticker2Data)
}
Теперь один экземпляр AnyTicker будет содержать либо Ticker1Data, либо Ticker2Data. Как только у вас есть экземпляр enum, вы можете узнать, какой это случай, и теперь связанные данные автоматически имеют правильный тип.