How to parse one block of JSON data instead of the entire JSON sequence

丶灬走出姿态 提交于 2019-12-20 05:59:24

问题


Below is the code that am using to parse a JSON api. The code works and i am able to parse all the JSON values into the struct below but i would like to know how to parse only the first block(?)/ array and store them in the struct so that i can perform operations on them.

     let jsonUrlString = "https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=EUR&to_symbol=USD&interval=5min&apikey=demo"

        let urlObj = URL(string: jsonUrlString)

        URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
            guard let data = data else { return }
            do {
                let forex = try JSONDecoder().decode(Root.self, from: data)
                print(forex.timeSeriesFX5Min)
            } catch {

                print(error)
            }

            }.resume()
    }
}

struct Root: Codable {
    let timeSeriesFX5Min: [String:Forex]

    enum CodingKeys: String, CodingKey {
        case timeSeriesFX5Min = "Time Series FX (5min)"
    }
}


    // MARK: - TimeSeriesFX5Min
    struct Forex: Codable {
        let the1Open, the2High, the3Low, the4Close: String

        enum CodingKeys: String, CodingKey {
            case the1Open = "1. open"
            case the2High = "2. high"
            case the3Low = "3. low"
            case the4Close = "4. close"
        }

    }

回答1:


I see two ways to do this, the first requires a change to the Root struct where we need to use the Meta Data part of the message

struct Root: Codable {
    let metaData: [String: String]
    let timeSeriesFX5Min: [String:Forex]

    enum CodingKeys: String, CodingKey {
        case timeSeriesFX5Min = "Time Series FX (5min)"
        case metaData = "Meta Data"
    }
}

Then we pick up the item labeled "Last Refresed" and use the value to look up the latest price entry in the time series dictionary

do {
    let forex = try JSONDecoder().decode(Root.self, from: data)
    print(forex.metaData)
    if let latestTime = forex.metaData["4. Last Refreshed"], let latestForex = forex.timeSeriesFX5Min[latestTime] {
        print(latestForex)
    }        
} catch {
    print(error)
}

Another option is to take advantage of the fact that the timestamps are given in such a format that they can be properly sorted so instead of using meta data we sort the keys and pick the last item

if let latestTime = forex.timeSeriesFX5Min.keys.sorted().last, let latestForex = forex.timeSeriesFX5Min[latestTime] {
     print(latestForex)
}



回答2:


When you make a request you probably will notify who call your method with the request value by callback right ? So you will create a new instance of your object or array object and fill with the result.

If you will create in this structure you just gonna take your arrayObject and use .first and do your logic following this...

Example:

var newRoot: [Root] = [] 
func loadRoot() {
    Service().makeRequest() { (result, error) int
         newRoot = result.results
         print(newRoot.first)
    }
}

The function "makeRequest()" will call the method that you wrote.

let jsonUrlString = "https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=EUR&to_symbol=USD&interval=5min&apikey=demo"

    let urlObj = URL(string: jsonUrlString)

    URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
        guard let data = data else { return }
        do {
            let forex = try JSONDecoder().decode(Root.self, from: data)
            print(forex.timeSeriesFX5Min)
        } catch {

            print(error)
        }

        }.resume()
}
}


来源:https://stackoverflow.com/questions/56669677/how-to-parse-one-block-of-json-data-instead-of-the-entire-json-sequence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!