Как преобразовать JSON в определение типа Go при использовании API в GO lang - PullRequest
0 голосов
/ 25 мая 2018

Я создаю приложение, которое использует API, затем также сохраняет данные json для обработки структур lang, а затем я сделаю конечные точки, которые будут предоставлять результаты для определенных вычислений.Я реализовал использование API, и сложная часть заключается в том, как сохранить данные таким образом, чтобы они понимали.Какой подход правильный?

Ниже приведен формат JSON, когда я делаю запрос.key меня интересует только Time Series (1min)

JSON

{
    "Meta Data": {
        "1. Information": "Intraday (1min) prices and volumes",
        "2. Symbol": "MSFT",
        "3. Last Refreshed": "2018-05-24 16:00:00",
        "4. Interval": "1min",
        "5. Output Size": "Compact",
        "6. Time Zone": "US/Eastern"
    },
    "Time Series (1min)": {
        "2018-05-24 16:00:00": {
            "1. open": "98.3050",
            "2. high": "98.3600",
            "3. low": "98.2500",
            "4. close": "98.3100",
            "5. volume": "2377114"
        },
        "2018-05-24 15:59:00": {
            "1. open": "98.2900",
            "2. high": "98.3300",
            "3. low": "98.2900",
            "4. close": "98.3000",
            "5. volume": "137133"
        },
        "2018-05-24 15:58:00": {
            "1. open": "98.2900",
            "2. high": "98.3000",
            "3. low": "98.2600",
            "4. close": "98.2900",
            "5. volume": "135875"
        },
        "2018-05-24 15:53:00": {
            "1. open": "98.2750",
            "2. high": "98.2950",
            "3. low": "98.2600",
            "4. close": "98.2700",
            "5. volume": "77959"
        }
    }
}

код

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "github.com/jmoiron/jsonq"
)

func main() {
    response, err := http.Get("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=demo")
    if err != nil {
        fmt.Printf("The HTTP request failed with error %s\n", err)
    } else {
        data, _ := ioutil.ReadAll(response.Body)
        // fmt.Println(string(data))
    }
}

1 Ответ

0 голосов
/ 25 мая 2018

К сожалению, эти данные плохо структурированы для упрощения демаршалирования с помощью инфраструктуры JSON golang.

Общий подход к демаршалированию данных, такой как этот пример, заключается в определении типа (или набора типов), который содержит структуруВы хотите и реализуете интерфейс json.Unmarshaler с логикой для проверки входящей структуры и заполнения требуемых структур вручную.

Например:

type Quote struct {
  Time                   string
  Open, High, Low, Close float32
  Volume                 int
}

type Quotes []Quote

func main() {
  qs := Quotes{}
  err := json.Unmarshal([]byte(jsonstr), &qs)
  if err != nil {
    panic(err)
  }
  fmt.Printf("%#v\n", qs)
}

const targetName = "Time Series (1min)"

func (qs *Quotes) UnmarshalJSON(bs []byte) error {
  // Unmarshal into a generic map
  obj := make(map[string]interface{})
  err := json.Unmarshal(bs, &obj)
  if err != nil {
    return err
  }

  // Find the target time series
  entries, ok := obj[targetName].(map[string]interface{})
  if !ok {
    return fmt.Errorf("cannot find entry with name %q", targetName)
  }

  // Parse a Quote object from each entry in the target object
  quotes := []Quote{}
  for timestamp, values := range entries {
    values, ok := values.(map[string]interface{})
    if !ok {
      return fmt.Errorf("value for %q is not an object", timestamp)
    }
    quote := Quote{}
    quote.Time = timestamp
    v, err := strconv.ParseFloat(values["1. open"].(string), 32)
    if err != nil {
      return err
    }
    quote.Open = float32(v)
    // Repeat for each of Close,High,Low,Volume...
    quotes = append(quotes, quote)
  }

  *qs = Quotes(quotes)
  return nil
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...