【问题标题】:How to append all elements from an element of JSON dictionary to an array with Alamofire and SwiftyJSON如何使用 Alamofire 和 SwiftyJSON 将 JSON 字典元素中的所有元素附加到数组中
【发布时间】:2019-01-22 14:29:46
【问题描述】:

我正在尝试在给定的 JSON 字典中附加从最新到最旧的所有收盘价。我使用的 URL 请求如下:

https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=AMZN&interval=60min&outputsize=full&apikey=5H2L6THH6BSCAMKO

如您所见,结果是一个按最近日期排序的字典,在该字典中,有多种选项,包括收盘价。可以在下面看到它的一点点。

{
"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 给出的顺序相同),而不必自己以编程方式传递日期?或者有什么其他方法可以达到同样的效果吗?

【问题讨论】:

    标签: ios json swift alamofire swifty-json


    【解决方案1】:

    这是Decodable 的独立建议。它比 SwiftyJSON 更加通用。您可以在 Playground 中对其进行测试。

    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) }
    

    【讨论】:

    • 非常感谢您的帮助!它打印每个对象给出的价格和日期,但是我怎么能为每个日期这样做,我只将价格附加到数组中?
    • 您可以通过let prices = result.map{$0.price}获取价格
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2021-08-14
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 2020-02-14
    相关资源
    最近更新 更多