问题
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