问题
I am trying to parse a stock api from Alpha Vantage
.
This is what a response looks like: API Response Demo
I set up Four classes to use for decoding and encoding:
- Stocks
- Meta Data
- Time Series
- Open High Low Close
I think the problem lies in the Time Series Classes since i am suppose to be getting an array dates as a Key, which each contain Open, Close, High, Low values. All three classes conform to the Codable
protocol.I changed the value of the keys in the enum so that it could match the correct JSON Response
.
var stocks = [Stocks]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
loadURL()
}
func loadURL(){
let stocksURL = URL(string: "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo")
print("Inside loadURL")
guard let url = stocksURL else { return }
if let data = try? Data(contentsOf: url){
print("Inside data")
parse(json: data)
}
}
func parse(json: Data){
let jsonDecoder = JSONDecoder()
print("before Decoding")
if let json = try? jsonDecoder.decode([Stocks].self, from: json){
print("Inside parsing")
stocks = json
print(stocks[0].meta_data.symbol)
print(stocks[0].time_series.OHLC[0].open)
}
}
}
class Stocks: Codable {
var meta_data: MetaData
var time_series: TimeSeries
enum CodingKeys: String, CodingKey {
case meta_data = "Meta Data"
case time_series = "Time Series (5min)"
}
}
class MetaData: Codable {
var information: String
var symbol: String
var lastRefreshed: String
var outputSize: String
var timeZone: String
enum CodingKeys: String, CodingKey {
case information = "1. Information"
case symbol = "2. Symbol"
case lastRefreshed = "3. Last Refreshed"
case outputSize = "4. Output Size"
case timeZone = "5. Time Zone"
}
}
class TimeSeries: Codable {
var OHLC: [OpenHighLowClose]
}
class OpenHighLowClose: Codable {
var open: Double
var high: Double
var low: Double
var close: Double
var volume: Double
enum CodingKeys: String, CodingKey {
case open = "1. open"
case high = "2. high"
case low = "3. low"
case close = "4. close"
case volume = "5. volume"
}
}
回答1:
Here are the proper data types w.r.t your response
// MARK: - Response
struct Response: Codable {
let metaData: MetaData
let timeSeries5Min: [String: TimeSeries5Min]
enum CodingKeys: String, CodingKey {
case metaData = "Meta Data"
case timeSeries5Min = "Time Series (5min)"
}
}
// MARK: - MetaData
struct MetaData: Codable {
let the1Information, the2Symbol, the3LastRefreshed, the4Interval: String
let the5OutputSize, the6TimeZone: String
enum CodingKeys: String, CodingKey {
case the1Information = "1. Information"
case the2Symbol = "2. Symbol"
case the3LastRefreshed = "3. Last Refreshed"
case the4Interval = "4. Interval"
case the5OutputSize = "5. Output Size"
case the6TimeZone = "6. Time Zone"
}
}
// MARK: - TimeSeries5Min
struct TimeSeries5Min: Codable {
let the1Open, the2High, the3Low, the4Close: String
let the5Volume: String
enum CodingKeys: String, CodingKey {
case the1Open = "1. open"
case the2High = "2. high"
case the3Low = "3. low"
case the4Close = "4. close"
case the5Volume = "5. volume"
}
}
Usage:
func loadURL() {
let stocksURL = URL(string: "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo")
URLSession.shared.dataTask(with: stocksURL!) { (data, response, error) in
if let error = error {
print(error)
return
}
do {
let response = try JSONDecoder().decode(Response.self, from: data!)
response.timeSeries5Min.forEach({ (keyValue) in
print(keyValue)
})
} catch {
print(error)
}
}.resume()
}
来源:https://stackoverflow.com/questions/56485249/parsing-a-stock-api-that-contain-dates-as-keys-using-the-codable-protocol