如何使用Alamofire和SwiftyJSON将JSON字典中的所有元素附加到数组 [英] How to append all elements from an element of JSON dictionary to an array with Alamofire and SwiftyJSON

查看:84
本文介绍了如何使用Alamofire和SwiftyJSON将JSON字典中的所有元素附加到数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to append all closing prices from the most recent to the oldest available in a given JSON dictionary. The URL request that I'm using is the following:

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

如您所见,结果是字典以最新日期排序,并且在该字典中有多种选择,包括关闭价钱。可以在下面看到一点。

As you can see, the result is a dictionary ordered with the most recent dates and within that dictionary, there is various options, including the closing price. A little bit of it can be seen below.

{
"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结构中进行一些操作以成功地以有序的方式请求每个日期的收盘价,当我尝试访问以前的日期时卡住了。我正在使用的功能如下。

Now, I want to append, from the most recent date and below it in order, the closing price. I've tried to use a for loop, while loops and playing a bit with the Date structure to successfully request the closing price of each date in an orderly fashion, however it gets stuck when I try to access a former date. The function I am using is the following one.

    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给出的顺序相同)而不必自己编程传递日期?还是有其他方法可以达到相同的结果?

Is there any way to append all elements from the array (In the same order as the api gives) without having to pass in the date programatically by myself? Or is any other way I could achieve the same result?

推荐答案

这是带有可解码 的独立建议。它比SwiftyJSON具有更多的用途。您可以在操场上对其进行测试。

This is a standalone suggestion with Decodable. It's much more versatile than SwiftyJSON. You can test it in a Playground.

结果是按结构 Price 排序的结构数组在日期降序之前。最好使用数组,因为字典是无序的。

The result is an array of struct Price sorted by date descending. An array is preferable because a dictionary is unordered.

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

这篇关于如何使用Alamofire和SwiftyJSON将JSON字典中的所有元素附加到数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆