I'm dabbling with GO for the first time and an API I'm using for getting stock prices accepts multiple tickers (think stock ids; NVDA => Nvidia) to cut down on my limited API calls. However when trying to get with multiple tickers, the body seems to get cut off:
{
"meta ": {
"requested ": 2,
"returned ": 2
},
"data ": [
{
"ticker ": "MSFT ",
"name ": "Microsoft Corporation ",
"exchange_short ": null,
"exchange_long ": null,
"mic_code ": "IEXG ",
"currency ": "USD ",
"price ": 374.72,
"day_high ": 376.92,
"day_low ": 373.54,
"day_open ": 374.94,
"52_week_high ": 349.84,
"52_week_low ": 213.43,
"market_cap ": null,
"previous_close_price ": 374.58,
"previous_close_price_time ": "2023-12-22T15:59:56.000000 ",
"day_change ": 0.04,
"volume ": 165558,
"is_extended_hours_price ": false,
"last_trade_time ": "2023-12-26T16:00:00.000000 "
},
{
"ticker ": ""
Making the exact call directly to the stock API in postman however returns:
{
"meta": {
"requested": 2,
"returned": 2
},
"data": [
{
"ticker": "MSFT",
"name": "Microsoft Corporation",
"exchange_short": null,
"exchange_long": null,
"mic_code": "IEXG",
"currency": "USD",
"price": 374.72,
"day_high": 376.92,
"day_low": 373.54,
"day_open": 374.94,
"52_week_high": 349.84,
"52_week_low": 213.43,
"market_cap": null,
"previous_close_price": 374.58,
"previous_close_price_time": "2023-12-22T15:59:56.000000",
"day_change": 0.04,
"volume": 165558,
"is_extended_hours_price": false,
"last_trade_time": "2023-12-26T16:00:00.000000"
},
{
"ticker": "PLTR",
"name": "Palantir Technologies Inc",
"exchange_short": null,
"exchange_long": null,
"mic_code": "IEXG",
"currency": "USD",
"price": 17.68,
"day_high": 17.75,
"day_low": 17.34,
"day_open": 17.45,
"52_week_high": 17.16,
"52_week_low": 5.92,
"market_cap": null,
"previous_close_price": 17.42,
"previous_close_price_time": "2023-12-22T15:59:56.000000",
"day_change": 1.47,
"volume": 236201,
"is_extended_hours_price": false,
"last_trade_time": "2023-12-26T15:59:58.000000"
}
]
}
I assume I'm doing something wrong (I've never touched GO before yesterday) Here is the relevant code:
func getStockPriceData(ticker string) []Stock {
baseURL, _ := url.Parse("https://api.stockdata.org")
baseURL.Path += "v1/data/quote"
params := url.Values{}
params.Add("symbols", ticker)
params.Add("api_token", apiToken.ApiToken)
baseURL.RawQuery = params.Encode()
req, _ := http.NewRequest("GET", baseURL.String(), nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
panic(err.Error())
}
apiResponseData := ApiResponseStockData{}
//json.NewDecoder(res.Body).Decode(&apiResponseData)
err2 := json.Unmarshal(body, &apiResponseData)
if err2 != nil {
fmt.Println("whoops:", err2)
}
stocks := []Stock{}
for _, data := range apiResponseData.ResponseStockData {
stock := Stock{}
stock.Name = data.Name
stock.Ticker = data.Ticker
stock.Price = data.Price
stock.DayHigh = data.DayHigh
stock.DayLow = data.DayLow
stock.DayOpen = data.DayOpen
stock.PreviousClosePrice = data.PreviousClosePrice
stock.DayChange = data.DayChange
stocks = append(stocks, stock)
}
return stocks
}
Structs for context:
type Stock struct {
Name string `json:"name"`
Ticker string `json:"ticker"`
Price float64 `json:"price"`
DayHigh float64 `json:"day_high"`
DayLow float64 `json:"day_low"`
DayOpen float64 `json:"day_open"`
DayChange float64 `json:"day_change"`
PreviousClosePrice float64 `json:"previous_close_price"`
}
type ApiResponseStockData struct {
ResponseStockData []ResponseData `json:"data"`
}
type ResponseData struct {
Name string `json:"name"`
Ticker string `json:"ticker"`
ExchangeShort bool `json:"exchange_short"`
ExchangeLong bool `json:"exchange_long"`
MicCode string `json:"mic_code"`
Currency string `json:"currency"`
Price float64 `json:"price"`
DayHigh float64 `json:"day_high"`
DayLow float64 `json:"day_low"`
DayOpen float64 `json:"day_open"`
DayChange float64 `json:"day_change"`
YearHigh float64 `json:"52_week_high"`
YearLow float64 `json:"52_week_low"`
MarketCap float64 `json:"market_cap"`
PreviousClosePrice float64 `json:"previous_close_price"`
PreviousCloseTime time.Time `json:"previous_close_time"`
Volume float64 `json:"volume"`
IsExtendedHoursPrice bool `json:"is_extended_hours_price"`
LastTradeTime time.Time `json:"last_trade_time"`
}
After reviewing a few threads I tried using both json.Unmarshal
and json.NewDecoder().Decode()
but still no luck. The cutoff string from above comes from body, and when using either the Decode
or Unmarshal
it successfully adds the single full object to apiResponseData
. I could understand if this was a colossal response, but this seems pretty simple, so I have to assume I'm making a pretty glaring rookie error.
Any help would be greatly appreciated.
You are trying to parse a time string using a format that includes the time zone offset ("Z07:00").
You need to adjust the time layout to the following.
layout := "2006-01-02T15:04:05.000000"
Your error handling is not proper that is why you are able to exit with incorrect responses as well.