Преобразование JSON массива чисел в CGPoints в Objective- C или Swift - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь преобразовать JSON из API в массив контрольных точек, которые я могу использовать в основной графике.

JSON выглядит так:

{"date":"2017-01-05","open":119.34,"high":120.2,"low":119.1,"close":119.7,"adjusted_close":109.7062,"volume":4261070},{"date":"2017-01-06","open":118.93,"high":121.5,"low":118.52,"close":120.76,"adjusted_close":110.6777,"volume":4089186},{"date":"2017-01-09","open":120.76,"high":121.06,"low":120.33,"close":120.43,"adjusted_close":110.3754,"volume":3021844}

I меня интересуют поля даты и закрытия, и я хотел бы преобразовать их в этот формат

 dataPoints:@[xy(val0,119.7),xy(val1,120.76),xy(val2,120.43)];

, где val0 ... val3 - даты, сопоставленные с измерением x графика, и я определил:

 #define xy(__x,__y) [NSValue valueWithCGPoint:CGPointMake(__x,__y)]

Я не привязан к #define. Это просто код, который сейчас использует CoreGraphics. Если есть другой способ сделать это, создайте структуру или что-то еще, что было бы здорово.

Я знаю, как декодировать JSON в массив, используя:

struct StockReport: Codable {
    let date: String
    let stockDatumOpen, high, low, close: Double
    let adjustedClose: Double
    let volume: Int

    enum CodingKeys: String, CodingKey {
        case date
        case stockDatumOpen = "open"
        case high, low, close
        case adjustedClose = "adjusted_close"
        case volume
    }
}

typealias StockData = [StockReport]

let stockData = try? newJSONDecoder().decode(StockData.self, from: jsonData)

Помимо этого, однако , Я не уверен, как создать массив точек CG.

Думаю, я могу преобразовать строки даты в секунды с 1970 года (эпохи), а затем масштабировать их в системе координат. Или я могу использовать индекс массива как целое число, соответствующее каждому дню, но насколько я понял. Следует ли мне пропустить oop через массив stockData и создавать точки одну за другой? Есть ли более элегантный способ?

Заранее благодарим за любые предложения.

1 Ответ

0 голосов
/ 11 июля 2020

Предполагая, что вы получаете действительную строку json (отправленная вами строка не является допустимой строкой json. Вы можете отсортировать свои объекты по дате (если они еще не отсортированы), перечислить элементы и инициализировать CGPoint следующим образом:

let json = """
    [{"date":"2017-01-05",
     "open":119.34,
     "high":120.2,
     "low":119.1,
     "close":119.7,
     "adjusted_close":109.7062,
     "volume":4261070},
    {"date":"2017-01-06",
     "open":118.93,
     "high":121.5,
     "low":118.52,
     "close":120.76,
     "adjusted_close":110.6777,
     "volume":4089186},
    {"date":"2017-01-09",
     "open":120.76,
     "high":121.06,
     "low":120.33,
     "close":120.43,
     "adjusted_close":110.3754,
     "volume":3021844}]
"""
do {
    let stocks = try JSONDecoder().decode([StockReport].self, from: Data(json.utf8))
    let points = stocks.sorted{$0.date < $1.date}.enumerated().map {
        CGPoint(x: Double($0.offset), y: $0.element.close)
    }
    print(points)
} catch {
    print(error)
}

Будет напечатано

[(0,0, 119,7), (1,0, 120,76), (2,0, 120,43)]

...