Golang:如何解析/反序列化/解码 JSON 数组 API 响应?

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

Golang :How to parse/unmarshal/decode a json array API response?

问题

我正在尝试解析来自维基百科API的响应,该API位于https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/Smithsonian_Institution/daily/20160101/20170101,并将其解析为一个结构体数组,然后我将打印出查看次数。

然而,我尝试实现此功能的代码在构建和运行时没有在终端中返回任何内容。

我无法成功的代码如下:

type Post struct {
	Project     string `json:"project"`
	Article     string `json:"article"`
	Granularity string `json:"granularity"`
	Timestamp   string `json:"timestamp"`
	Access      string `json:"access"`
	Agent       string `json:"agent"`
	Views       int    `json:"views"`
}

func main() {
	//The name of the wikipedia post
	postName := "Smithsonian_Institution"

	//The frequency of
	period := "daily"

	//When to start the selection
	startDate := "20160101"

	//When to end the selection
	endDate := "20170101"

	url := fmt.Sprintf("https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/%s/%s/%s/%s", postName, period, startDate, endDate)

	//Get from URL
	req, err := http.Get(url)
	if err != nil {
		return
	}
	defer req.Body.Close()

	var posts []Post

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		panic(err.Error())
	}

	json.Unmarshal(body, &posts)

	// Loop over structs and display the respective views.
	for p := range posts {
		fmt.Printf("Views = %v", posts[p].Views)
		fmt.Println()
	}
}

请问,从上述API接收JSON响应并将其解析为结构体数组的最佳方法是什么,然后可以将其插入到数据存储中或相应地打印出来。

谢谢。

英文:

I am trying to parse the response from Wikipedia's API located at https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/Smithsonian_Institution/daily/20160101/20170101 into an array of structs of which I will proceed to print out the view count

However, the code that I have tried to implement in order to achieve this returns nothing in the terminal when I build and run it?

The code I am failing to succeed with is as follows.

   type Post struct {
	Project string `json:"project"`
	Article string `json:"article"`
	Granularity string `json:"granularity"`
	Timestamp string `json:"timestamp"`
	Access string `json:"access"`
	Agent string `json:"agent"`
	Views int `json:"views"`
}

func main(){
	//The name of the wikipedia post
	postName := "Smithsonian_Institution"

	//The frequency of
	period := "daily"

	//When to start the selection
	startDate := "20160101"

	//When to end the selection
	endDate := "20170101"

	url := fmt.Sprintf("https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/%s/%s/%s/%s", postName, period, startDate, endDate)

	//Get from URL
	req, err := http.Get(url)
	if err != nil{
		return
	}
	defer req.Body.Close()

	var posts []Post

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		panic(err.Error())
	}

	json.Unmarshal(body, &posts)

	// Loop over structs and display the respective views.
	for p := range posts {
		fmt.Printf("Views = %v", posts

.Views) fmt.Println() } }

What is the optimal method of receiving a json response from a API such as the one mentioned above and thereafter parsing that array into an array of structs, which can then be inserted into a datastore or printed out accordingly.

Thanks

答案1

得分: 19

结构声明可以嵌套在彼此内部。

以下结构应该可以从该JSON转换而来:

type resp struct {
    Items []struct {
        Project     string `json:"project"`
        Article     string `json:"article"`
        Granularity string `json:"granularity"`
        Timestamp   string `json:"timestamp"`
        Access      string `json:"access"`
        Agent       string `json:"agent"`
        Views       int    `json:"views"`
    } `json:"items"`
}

我使用 json-to-go 生成了上述代码,这是一个在使用JSON API时非常方便的时间节省工具。

英文:

Struct declarations can be nested inside one another.

The following struct should be convertable from that json:

type resp struct {
	Items []struct {
		Project string `json:"project"`
		Article string `json:"article"`
		Granularity string `json:"granularity"`
		Timestamp string `json:"timestamp"`
		Access string `json:"access"`
		Agent string `json:"agent"`
		Views int `json:"views"`
	} `json:"items"`
}

I generated that with json-to-go, which is a great time saver when working with JSON APIs.

答案2

得分: 9

你的解决方案:

data := struct {
    Items []struct {
        Project     string `json:"project"`
        Article     string `json:"article"`
        Granularity string `json:"granularity"`
        Timestamp   string `json:"timestamp"`
        Access      string `json:"access"`
        Agent       string `json:"agent"`
        Views       int    `json:"views"`
    } `json:"items"`
}{}

// 你不需要将 body 转换为 []byte,ReadAll 返回 []byte

err := json.Unmarshal(body, &data)
if err != nil { // 不要忘记处理错误
}
英文:

Your solution:

data := struct {
	Items []struct {
		Project string `json:"project"`
		Article string `json:"article"`
		Granularity string `json:"granularity"`
		Timestamp string `json:"timestamp"`
		Access string `json:"access"`
		Agent string `json:"agent"`
		Views int `json:"views"`
	} `json:"items"`
}{}

// you don't need to convert body to []byte, ReadAll returns []byte

err := json.Unmarshal(body, &data)
if err != nil { // don't forget handle errors
}

huangapple
  • 本文由 发表于 2017年4月26日 11:18:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/43624404.html
匿名

发表评论

匿名网友

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

确定