获取GO中嵌套JSON结构的数组。

huangapple go评论91阅读模式
英文:

Get Array of Nested JSON Struct in GO

问题

我是新手GoLang,对于从嵌套的JSON数据中填充数组有一个问题。我昨天在Stack Overflow上查找了一下,但没有找到确切的主题,只有一些类似的帖子,但没有提供直接的解决方案。

假设我有一些嵌套的JSON数据,如下所示:

我应该如何创建一个嵌套的结构来填充一个包含收盘价格的数组。我的代码如下所示。
我的目标是拥有一个数组,其中arr = {157.92, 142.19, 148.26}

提前感谢!非常感谢任何帮助!

{
  "history": {
    "day": [
      {
        "date": "2019-01-02",
        "open": 154.89,
        "high": 158.85,
        "low": 154.23,
        "close": 157.92,
        "volume": 37039737
      },
      {
        "date": "2019-01-03",
        "open": 143.98,
        "high": 145.72,
        "low": 142.0,
        "close": 142.19,
        "volume": 91312195
      },
      {
        "date": "2019-01-04",
        "open": 144.53,
        "high": 148.5499,
        "low": 143.8,
        "close": 148.26,
        "volume": 58607070
      }
      ...
    ]
  }
}
// 数据结构
type Hist struct {
	History string `json:"history"`
}

type Date struct {
	Day string `json:"day"`
}

type Price struct {
	Close []string `json:"close"`
}

// 历史报价
func get_quotes(arg1 string, arg2 string, arg3 string, arg4 string) []string {

	// arg1 = 股票代码, arg2 = 开始日期, arg3 = 结束日期, arg4 = 访问令牌

	// TRADIER API
	apiUrl := "https://sandbox.tradier.com/v1/markets/history?symbol=" + arg1 + "&interval=daily&start=" + arg2 + "&end=" + arg3

	u, _ := url.ParseRequestURI(apiUrl)
	urlStr := u.String()

	client := &http.Client{}
	r, _ := http.NewRequest("GET", urlStr, nil)
	r.Header.Add("Authorization", "Bearer "+arg4)
	r.Header.Add("Accept", "application/json")

	resp, _ := client.Do(r)
	responseData, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Status)
	fmt.Println(string(responseData))

	var response Price
	json.NewDecoder(resp.Body).Decode(&response)

	fmt.Println(response.Close)

	return response.Close

}
英文:

I am new to GoLang, and have a question about filling an array from nested JSON data. I have looked through Stack overflow yesterday and cannot find this exact topic, only threads that are similar, but do not provide a direct solution.

Lets say I have some nested JSON data like what is given below:

How can I create a nested struct to fill an array of the close prices. My code is given below.
My goal is to have an array where, arr = {157.92, 142.19, 148.26}

Thanks in advance! I greatly appreciate any help!

{
  "history": {
    "day": [
      {
        "date": "2019-01-02",
        "open": 154.89,
        "high": 158.85,
        "low": 154.23,
        "close": 157.92,
        "volume": 37039737
      },
      {
        "date": "2019-01-03",
        "open": 143.98,
        "high": 145.72,
        "low": 142.0,
        "close": 142.19,
        "volume": 91312195
      },
      {
        "date": "2019-01-04",
        "open": 144.53,
        "high": 148.5499,
        "low": 143.8,
        "close": 148.26,
        "volume": 58607070
      }
      ...
    ]
  }
}
// DATA STRUCTURE
type Hist struct {
	History string `json:"history"`
}

type Date struct {
	Day string `json:"day"`
}

type Price struct {
	Close []string `json:"close"`
}

// HISTORICAL QUOTES
func get_quotes(arg1 string, arg2 string, arg3 string, arg4 string) []string {

	// arg1 = ticker symbol, arg2 = start, arg3 = end, arg4 = access token

	// TRADIER API
	apiUrl := "https://sandbox.tradier.com/v1/markets/history?symbol=" + arg1 + "&interval=daily&start=" + arg2 + "&end=" + arg3

	u, _ := url.ParseRequestURI(apiUrl)
	urlStr := u.String()

	client := &http.Client{}
	r, _ := http.NewRequest("GET", urlStr, nil)
	r.Header.Add("Authorization", "Bearer "+arg4)
	r.Header.Add("Accept", "application/json")

	resp, _ := client.Do(r)
	responseData, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Status)
	fmt.Println(string(responseData))

	var response Price
	json.NewDecoder(resp.Body).Decode(&response)

	fmt.Println(response.Close)

	return response.Close

}

答案1

得分: 4

以下是翻译好的内容:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type Response struct {
	History History `json:"history"`
}
type Day struct {
	Date   string  `json:"date"`
	Open   float64 `json:"open"`
	High   float64 `json:"high"`
	Low    float64 `json:"low"`
	Close  float64 `json:"close"`
	Volume int     `json:"volume"`
}
type History struct {
	Day []Day `json:"day"`
}

func main() {
	prices, err := closePrices()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(prices)
}

func closePrices() (out []float64, err error) {
	resp, err := http.Get("...")
	if err != nil {
		return
	}
	r := Response{}
	err = json.NewDecoder(resp.Body).Decode(&r)
	if err != nil {
		return
	}
	for _, d := range r.History.Day {
		out = append(out, d.Close)
	}
	return
}

这段代码应该能满足你的需求。你的数据结构没有正确地反映API的响应。我使用了这个工具来快速将JSON值转换为Go结构体类型。一旦你正确解码了响应,只需要遍历每个Day结构并将close值追加到输出数组中。

我添加了解码和映射值的核心部分。你可以通过组合你已经拥有的内容来自定义客户端、请求和标头。

请注意,代码中的http.Get("...")需要替换为你实际的API请求地址。

英文:

Something like this should give you what you need. Your data structure does not correctly reflect the response from the API. I used this tool to quickly convert the JSON value into a Go struct type. Once you're decoding the response correctly, then it's just a matter of iterating over each Day struct and appending the close value to an output array.

I added the core stuff for decoding and mapping the values. You can handle customizing the client, request, and headers however you'd like by combining what you've already got.

package main

import (
	"encoding/json"
	"fmt"
    "log"
	"net/http"
)

type Response struct {
	History History `json:"history"`
}
type Day struct {
	Date   string  `json:"date"`
	Open   float64 `json:"open"`
	High   float64 `json:"high"`
	Low    float64 `json:"low"`
	Close  float64 `json:"close"`
	Volume int     `json:"volume"`
}
type History struct {
	Day []Day `json:"day"`
}

func main() {
	prices, err := closePrices()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(prices)
}

func closePrices() (out []float64, err error) {
	resp, err := http.Get("...")
	if err != nil {
		return
	}
	r := Response{}
	err = json.NewDecoder(resp.Body).Decode(&r)
	if err != nil {
		return
	}
	for _, d := range r.History.Day {
		out = append(out, d.Close)
	}
	return
}

huangapple
  • 本文由 发表于 2021年6月4日 03:01:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/67827329.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定