我正在尝试在给定的JSON字典中附加所有收盘价(从最新到最晚)。我正在使用的URL请求如下:
如您所见,结果是按最近日期排序的字典,并且在该字典中有多种选择,包括收盘价。可以在下面看到一点。
{
"Meta Data": {
"1. Information": "Intraday (60min) open, high, low, close prices and volume",
"2. Symbol": "AMZN",
"3. Last Refreshed": "2018-08-15 12:30:00",
"4. Interval": "60min",
"5. Output Size": "Full size",
"6. Time Zone": "US/Eastern"
},
"Time Series (60min)": {
"2018-08-15 12:30:00": {
"1. open": "1892.1620",
"2. high": "1898.0000",
"3. low": "1879.3600",
"4. close": "1892.5000",
"5. volume": "893752"
},
"2018-08-15 11:30:00": {
"1. open": "1873.4399",
"2. high": "1893.3500",
"3. low": "1873.4399",
"4. close": "1892.1200",
"5. volume": "798959"
},
"2018-08-15 10:30:00": {
"1. open": "1905.1899",
"2. high": "1915.5300",
"3. low": "1871.0200",
"4. close": "1871.0200",
"5. volume": "1614045"
},
现在,我想从最近的日期开始并在其后的顺序附加收盘价。我尝试使用for循环,while循环和Date结构,以有序方式成功请求每个日期的收盘价,但是当我尝试访问以前的日期时,它会卡住。我正在使用的功能如下。
func get1HPriceArr(stock:String, dataPoints:Int){
let url = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=\(stock)&interval=60min&outputsize=full&apikey=5H2L6THH6BSCAMKO"
Alamofire.request(url, method: .get).validate().responseJSON { response in
switch response.result {
case .success(let value):
let timeZone = TimeZone(secondsFromGMT: 0000)
let dateFormatter = DateFormatter()
dateFormatter.timeZone = timeZone!
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let json = JSON(value)
var DatesArray:[String] = []
var ClosingPrices:[Double] = []
var followingDate:String?
func AddDates() -> [Double]{
print("FollowingDate just below the func is \(followingDate)")
while ClosingPrices.count != dataPoints {
print("Following date in the while loop is \(followingDate)")
let mostRecentRefreshed = json["Meta Data"]["3. Last Refreshed"].stringValue
print("Most recent refreshed is \(mostRecentRefreshed)")
if followingDate == nil {
followingDate = mostRecentRefreshed
let closingPrice = json["Time Series (60min)"][followingDate!]["4. close"].doubleValue
print("Following Date was nil and now its value is \(followingDate!)")
DatesArray.append(followingDate!)
ClosingPrices.append(closingPrice)
print(ClosingPrices)
// You must check if most recent refreshed is 16:00
let followingDateDate = dateFormatter.date(from: followingDate!)
let hour = Calendar.current.component(.hour, from: followingDateDate!)
let minutes = Calendar.current.component(.minute, from: followingDateDate!)
if hour == 16{
let halfNHourMore = Calendar.current.date(byAdding: .minute,value: 30, to: followingDateDate!)
let dateStringNil = dateFormatter.string(from: halfNHourMore!)
followingDate = dateStringNil
} else {
print("Last refreshed time is not 16:00, so following date was nil and now is \(followingDate)")
}
}
print("Following date is \(String(describing: followingDate))")
var currentDate = dateFormatter.date(from: followingDate!)
print("Current Date is \(currentDate)")
let dateHour = Calendar.current.component(.hour, from: currentDate!)
let dateMinutes = Calendar.current.component(.minute, from: currentDate!)
var oneHourLess:Date!
if dateHour == 16 && dateMinutes == 0 {
oneHourLess = Calendar.current.date(byAdding: .minute,value: -30, to: currentDate!)
} else {
oneHourLess = Calendar.current.date(byAdding: .hour,value: -1, to: currentDate!)
}
let dateString = dateFormatter.string(from: oneHourLess!)
if (dateString.contains("17:30:00")) || (dateString.contains("18:30:00")) || (dateString.contains("19:30:00")) || (dateString.contains("20:30:00")) || (dateString.contains("21:30:00")) || (dateString.contains("22:30:00")) || (dateString.contains("23:30:00")) || (dateString.contains("00:30:00")) || (dateString.contains("01:30:00")) || (dateString.contains("02:30:00")) || (dateString.contains("03:30:00")) || (dateString.contains("04:30:00")) || (dateString.contains("05:30:00")) || dateString.contains("06:30:00") || dateString.contains("05:30:)0") || dateString.contains("06:30:00") || dateString.contains("07:30:00") || dateString.contains("08:30:00") || dateString.contains("09:30:00") {
print("OneHourLess is \(oneHourLess)")
print("Its closing time since the time is \(dateString)")
} else {
DatesArray.append(dateString)
followingDate = dateString
print("Following date is \(String(describing: followingDate))")
currentDate = dateFormatter.date(from: followingDate!)
let closingPrice = json["Time Series (60min)"][followingDate!]["4. close"].doubleValue
let weekday = Calendar.current.component(.weekday, from: currentDate!)
let hour = Calendar.current.component(.hour, from: currentDate!)
let minutes = Calendar.current.component(.minute, from: currentDate!)
print("Weekday is \(weekday)")
print("Hour is \(hour)h")
print("Minutes are \(minutes)min")
ClosingPrices.append(closingPrice)
print("Closing prices count is \(ClosingPrices.count)")
print("Closing prices array is \(ClosingPrices)")
let oneDayLess = Calendar.current.date(byAdding: .day,value: -1, to: currentDate!)
let oneDayLessString = dateFormatter.string(from: oneDayLess!)
followingDate = oneDayLessString
print("Following date minus one day is \(followingDate)")
}
}
print(DatesArray)
print("Closing prices are \(ClosingPrices)")
return ClosingPrices
}
AddDates()
case .failure(let error):
print(error)
}
}
} // End of get1HPriceArr()
是否有任何方法可以添加数组中的所有元素(按api给出的顺序),而不必自己编程地传递日期?还是有其他方法可以达到相同的结果?
答案 0 :(得分:2)
这是Decodable
的独立建议。它比SwiftyJSON更具通用性。您可以在操场上对其进行测试。
result
是结构Price
的数组,按date
降序排列。最好使用数组,因为字典是无序的。
JSON
let jsonString = """
{
"Meta Data": {
"1. Information": "Intraday (60min) open, high, low, close prices and volume",
"2. Symbol": "AMZN",
"3. Last Refreshed": "2018-08-15 12:30:00",
"4. Interval": "60min",
"5. Output Size": "Full size",
"6. Time Zone": "US/Eastern"
},
"Time Series (60min)": {
"2018-08-15 12:30:00": {
"1. open": "1892.1620",
"2. high": "1898.0000",
"3. low": "1879.3600",
"4. close": "1892.5000",
"5. volume": "893752"
},
"2018-08-15 11:30:00": {
"1. open": "1873.4399",
"2. high": "1893.3500",
"3. low": "1873.4399",
"4. close": "1892.1200",
"5. volume": "798959"
},
"2018-08-15 10:30:00": {
"1. open": "1905.1899",
"2. high": "1915.5300",
"3. low": "1871.0200",
"4. close": "1871.0200",
"5. volume": "1614045"
}
}
}
"""
结构
struct Stocks: Decodable {
enum CodingKeys: String, CodingKey { case timeSeries = "Time Series (60min)"}
struct TimeSerie: Decodable {
let close : String
enum CodingKeys: String, CodingKey { case close = "4. close" }
}
let timeSeries : [String:TimeSerie]
}
struct Price {
let date : Date
let price : Double
}
解析
let data = Data(jsonString.utf8)
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
do {
let stocks = try decoder.decode(Stocks.self, from: data)
let result = stocks.timeSeries.map { (key: String, value: Stocks.TimeSerie) -> Price in
return Price(date: dateFormatter.date(from: key)!, price: Double(value.close)!)
}.sorted(by: {$0.date > $1.date})
print(result)
} catch { print(error) }