Reputation: 1177
I need to parse JSON from an API to get two arrays of data, one for Times, and one for Prices.
Here is the request:
func getReq(arr: Bool, completion: @escaping (Bool) -> ()){
Dates.shared.formatDate()
switch graphSetup {
case .day:
days = "1"
case .week:
days = "14"
}
let url = "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=1"
Alamofire.request(url).responseJSON { response in
switch response.result {
case .failure(let error):
// Do whatever here
return
case .success(let data):
// First make sure you got back a dictionary if that's what you expect
let responseJSON = JSON(response.result.value!)
if responseJSON.count != 0 {
//do whatever you want with your object json
parse(json: responseJSON)
print(responseJSON)
let gd = responseJSON["prices"].arrayValue
completion(arr)
}
}
}
This is exactly what JSON returns (print(responseJSON) I shortened it.
let json = "{
"prices" : [
[
1535841336422,
7186.4600704446984
],
[
1535841628453,
7187.2085293179398
],
[
1535841936398,
7189.7057414152769
],
... many others ...,
[
1535889024161,
7210.4807839639352
],
[
1535889339150,
7211.0670314913395
]
]
}"
After parsing, I get this array of arrays. How can I separate the times from the prices while keeping them in the correct order so that I can create a chart with [Times] as the x-axis and [Prices] as the y?
I am thinking something like this:
var times: [Int] = [] // Will probably convert to traditional date for chart
var prices: [Double] = []
So I end up with:
print(times)
[1535837138223,1535837424517,1535837741575,...]
print(prices)
[5560.902754859002,5542.734892949798,5539.4334214537,...]
and can now set up my chart correctly. How can I do this? Alternatively, if there is a better way to set up my chart data, (I am using danielgindi/Charts for iOS) please let me know.
Upvotes: 0
Views: 187
Reputation: 236360
You need to structure your data and create a custom encoder/decoder to encode/decode your array of different data types UInt64 (epoch unix time) and Double (price):
struct Root: Codable {
let prices: [Price]
}
struct Price: Codable {
let date: Date
let price: Double
}
extension Price {
public init(from decoder: Decoder) throws {
var unkeyedContainer = try decoder.unkeyedContainer()
let date = try unkeyedContainer.decode(UInt64.self).date
let price = try unkeyedContainer.decode(Double.self)
self.init(date: date, price: price)
}
public func encode(to encoder: Encoder) throws {
var unkeyedContainer = encoder.unkeyedContainer()
try unkeyedContainer.encode(date.unixEpochTime)
try unkeyedContainer.encode(price)
}
}
extension UInt64 {
var date: Date {
return Date(timeIntervalSince1970: TimeInterval(self)/1000)
}
}
extension Date {
var unixEpochTime: UInt64 {
return UInt64(timeIntervalSince1970*1000)
}
}
Playground testing:
let json = """
{"prices": [[1535837138223,5560.902754859002],
[1535837424517,5542.734892949798],
[1535837741575,5539.4334214537]]}
"""
do {
let prices = try JSONDecoder().decode(Root.self, from: Data(json.utf8)).prices
print(prices.first!.date.description(with:.current)) // "Saturday, September 1, 2018 at 6:25:38 PM Brasilia Standard Time\n"
print(prices.first!.price) // "5560.902754859\n"
} catch {
print(error)
}
Upvotes: 1