Фактический объект JSON довольно необычен - и он не поддается простому способу превращения его в структуру.
Для демонстрации я буду использовать JSONGen , aотличная утилита для превращения JSON в структуры Go.
Для решения данной проблемы я, вероятно, использовал бы двухэтапный подход.
Сначала проанализируйте весь документ (предполагая, что msft.json содержит APIответ):
$ cat msft.json | JSONGen
type _ struct {
MetaData struct {
Information string `json:"1. Information"`
Interval string `json:"4. Interval"`
LastRefreshed string `json:"3. Last Refreshed"`
OutputSize string `json:"5. Output Size"`
Symbol string `json:"2. Symbol"`
TimeZone string `json:"6. Time Zone"`
} `json:"Meta Data"`
TimeSeries1min struct {
_ struct {
Close string `json:"4. close"`
High string `json:"2. high"`
...
Проблема заключается в повторяющихся элементах с указанием даты и времени, которые, вероятно, лучше смоделировать в виде списка.В любом случае, с помощью jq мы можем разобрать соответствующий фрагмент и сгенерировать другую структуру:
$ cat msft.json | jq '.["Time Series (1min)"]["2018-05-24 15:47:00"]' | JSONGen
type _ struct {
Close string `json:"4. close"`
High string `json:"2. high"`
Low string `json:"3. low"`
Open string `json:"1. open"`
Volume string `json:"5. volume"`
}
Теперь мы можем объединить две структуры в одну.Вот полная программа для анализа входных данных JSON.
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Item struct {
Close string `json:"4. close"`
High string `json:"2. high"`
Low string `json:"3. low"`
Open string `json:"1. open"`
Volume string `json:"5. volume"`
}
type Response struct {
MetaData struct {
Information string `json:"1. Information"`
Interval string `json:"4. Interval"`
LastRefreshed string `json:"3. Last Refreshed"`
OutputSize string `json:"5. Output Size"`
Symbol string `json:"2. Symbol"`
TimeZone string `json:"6. Time Zone"`
} `json:"Meta Data"`
TimeSeries1min map[string]Item `json:"Time Series (1min)"`
}
Мы можем смоделировать временной ряд как карту элементов OHLC.Синтаксический анализ теперь становится действительно простым:
func main() {
resp := Response{}
if err := json.NewDecoder(os.Stdin).Decode(&resp); err != nil {
log.Fatal(err)
}
for k, v := range resp.TimeSeries1min {
fmt.Printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
resp.MetaData.Symbol, resp.MetaData.LastRefreshed, k,
v.Open, v.High, v.Low, v.Close)
}
}
Пока выводится что-то вроде:
$ go run main.go < msft.json
MSFT 2018-05-25 10:53:00 2018-05-25 10:49:00 98.6292 98.6292 98.5700 98.5750
MSFT 2018-05-25 10:53:00 2018-05-25 10:40:00 98.8700 98.8701 98.7900 98.8300
MSFT 2018-05-25 10:53:00 2018-05-25 10:22:00 98.6460 98.6500 98.6000 98.6300
...