如何从Go的http.Request中检索对象?

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

How to retrieve object from Go http.Request?

问题

我有一个可以接收HTTP GET参数的工作应用程序。到目前为止,它们一直是字符串和整数,并且通过以下方式成功获取每个字段:

http.Request.FormValue("field")

但是现在我在参数中添加了一个简单对象的数组,我不知道如何将其转换为Go结构的切片。

所涉及的数组是:

mods:[{
    name : x,
    max : 1,
    min : 2
 },{
    name:y,...
 }]

所以我不确定如何继续将其映射到Go结构。我应该先创建结构,然后使用JSON映射r.FormValue的结果吗?

英文:

I have a working app that recieves HTTP GET parameters. They've been Strings and ints until now and it has worked fine getting each field using

http.Request.FormValue("field")

But now I've added an array of simple objects in the parameters and I don't know how to transform it to a slice of Go structs.

The array in question is

mods:[{
    name : x,
    max : 1,
    min : 2
 },{
    name:y,...
 }]

So I'm not sure how to proceed to map it to a Go struct. Should I create the struct first and map the result of r.FormValue using JSON?

答案1

得分: 2

假设你想获取一组GitHub用户并打印他们的昵称(api.github.com中的Login字段)。

给定一个用户数组示例:

[{
  "login": "simonjefford",
  "id": 136,
  "avatar_url": "https://avatars1.githubusercontent.com/u/136?v=3",
  "gravatar_id": "",
  "url": "https://api.github.com/users/simonjefford",
  "html_url": "https://github.com/simonjefford",
  "followers_url": "https://api.github.com/users/simonjefford/followers",
  "following_url": "https://api.github.com/users/simonjefford/following{/other_user}",
  "gists_url": "https://api.github.com/users/simonjefford/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/simonjefford/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/simonjefford/subscriptions",
  "organizations_url": "https://api.github.com/users/simonjefford/orgs",
  "repos_url": "https://api.github.com/users/simonjefford/repos",
  "events_url": "https://api.github.com/users/simonjefford/events{/privacy}",
  "received_events_url": "https://api.github.com/users/simonjefford/received_events",
  "type": "User",
  "site_admin": false
}]

你需要一个适当的结构来处理它:

type Users []struct {
  Login             string `json:"login"`
  ID                int    `json:"id"`
  AvatarURL         string `json:"avatar_url"`
  GravatarID        string `json:"gravatar_id"`
  URL               string `json:"url"`
  HTMLURL           string `json:"html_url"`
  FollowersURL      string `json:"followers_url"`
  FollowingURL      string `json:"following_url"`
  GistsURL          string `json:"gists_url"`
  StarredURL        string `json:"starred_url"`
  SubscriptionsURL  string `json:"subscriptions_url"`
  OrganizationsURL  string `json:"organizations_url"`
  ReposURL          string `json:"repos_url"`
  EventsURL         string `json:"events_url"`
  ReceivedEventsURL string `json:"received_events_url"`
  Type              string `json:"type"`
  SiteAdmin         bool   `json:"site_admin"`
}

我建议你使用json-to-go来根据JSON生成一个漂亮干净的结构。

然后你可以进行以下操作:

package main

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

func main() {

  response, err := http.Get("https://api.github.com/users?since=135")
  if err != nil {
     log.Fatal(err)
  } else {

    defer response.Body.Close()
    users := UnmarshalUsers(response)
    for _, u := range users {
        // 打印每个用户的登录昵称
        fmt.Println(u.Login)
    }

  }

}

func UnmarshalUsers(r *http.Response) Users {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}
	var users Users
	err = json.Unmarshal(body, &users)
	if err != nil {
		panic(err)
	}

	return users
}

其中UnmarshalUsers函数定义如下:

func UnmarshalUsers(r *http.Response) Users {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}
	var users Users
	err = json.Unmarshal(body, &users)
	if err != nil {
		panic(err)
	}

	return users
}
英文:

Let's say you want to fetch a set of github users and want to print their nicknames (Login field in api.github.com).

Given a User array example:

[{
  "login": "simonjefford",
  "id": 136,
  "avatar_url": "https://avatars1.githubusercontent.com/u/136?v=3",
  "gravatar_id": "",
  "url": "https://api.github.com/users/simonjefford",
  "html_url": "https://github.com/simonjefford",
  "followers_url": "https://api.github.com/users/simonjefford/followers",
  "following_url": "https://api.github.com/users/simonjefford/following{/other_user}",
  "gists_url": "https://api.github.com/users/simonjefford/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/simonjefford/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/simonjefford/subscriptions",
  "organizations_url": "https://api.github.com/users/simonjefford/orgs",
  "repos_url": "https://api.github.com/users/simonjefford/repos",
  "events_url": "https://api.github.com/users/simonjefford/events{/privacy}",
  "received_events_url": "https://api.github.com/users/simonjefford/received_events",
  "type": "User",
  "site_admin": false
}]

You need a proper struct to handle it:

type Users []struct {
  Login string `json:"login"`
  ID int `json:"id"`
  AvatarURL string `json:"avatar_url"`
  GravatarID string `json:"gravatar_id"`
  URL string `json:"url"`
  HTMLURL string `json:"html_url"`
  FollowersURL string `json:"followers_url"`
  FollowingURL string `json:"following_url"`
  GistsURL string `json:"gists_url"`
  StarredURL string `json:"starred_url"`
  SubscriptionsURL string `json:"subscriptions_url"`
  OrganizationsURL string `json:"organizations_url"`
  ReposURL string `json:"repos_url"`
  EventsURL string `json:"events_url"`
  ReceivedEventsURL string `json:"received_events_url"`
  Type string `json:"type"`
  SiteAdmin bool `json:"site_admin"`
}

I suggest you to use json-to-go to have a nice a clean struct given a json.

Then you can do the following:

package main

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

func main() {

  response, err := http.Get("https://api.github.com/users?since=135")
  if err != nil {
     log.Fatal(err)
  } else {

    defer response.Body.Close()
    users := UnmarshalUsers(response)
    for _, u := range users {
        //Print each user's Login nickname
        fmt.Println(u.Login)
    }

  }

}

Where UnmarshalUsers is

func UnmarshalUsers(r *http.Response) Users {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}
	var users Users
	err = json.Unmarshal(body, &users)
	if err != nil {
		panic(err)
	}

	return users
}

答案2

得分: 0

请查看encoding/json包。在Go语言中,你需要将Go结构体编组(marshal)和解组(unmarshal)为它们的编码形式。这并不是一个快速简单的过程,但对于像Go这样的强类型语言来说,这是一个很好的现代解决方案。

在你的情况下,你需要创建一个与你要提取的JSON结构相匹配的结构体,然后将JSON解组为你创建的结构体类型的变量。

英文:

Check out the encoding/json package. In Go, you have to marshal and unmarshal your Go structures into and out of their encoding. It isn't quick an easy, but it's an good modern solution for a strictly typed language like Go.

In your case, you'll want to create a struct that matches the structure of the json you are trying to extract, and then unmarshal the json into a variable of the struct type you created.

huangapple
  • 本文由 发表于 2017年6月4日 06:32:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/44349115.html
匿名

发表评论

匿名网友

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

确定