英文:
Convert URL.Query (map of slices) to struct golang
问题
从标准库的URL.Query()到一个结构体的直接映射会很棒。
Query()
返回一个类似于以下的映射:
map[a:[aaaa] b:[bbbb] c:[cccc]]
结构体如下所示:
type Thing struct {
A string
B string
C string
}
- 我不知道为什么URL.Query返回一个包含数组元素的映射(嗯...我知道为什么,但是一个
GET
请求不太可能有重复的参数)
英文:
It would be awesome to have a straight forward mapping from the standard library URL.Query() to an struct.
Query()
returns a map like:
map[a:[aaaa] b:[bbbb] c:[cccc]]
The struct looks like:
type Thing struct {
A string
B string
C string
}
- I've no idea why URL.Query returns a map with array elements inside tough. (well.. I know why but a
GET
is not likely to have duplicated params)
答案1
得分: 14
请查看以下完整示例,该示例演示了如何直接在golang结构体中解析GET查询参数,然后将结构体作为响应发送回去。
package main
import (
"log"
"net/http"
"encoding/json"
"github.com/gorilla/schema"
)
var decoder = schema.NewDecoder()
type EmployeeStruct struct {
MemberId string `schema:"memberId"`
ActivityType string `schema:"activityType"`
BusinessUnitCode int `schema:"businessUnitCode"`
}
func GetEmployee(w http.ResponseWriter, r *http.Request) {
var employeeStruct EmployeeStruct
err := decoder.Decode(&employeeStruct, r.URL.Query())
if err != nil {
log.Println("Error in GET parameters: ", err)
} else {
log.Println("GET parameters: ", employeeStruct)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(employeeStruct)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/GetEmployee", GetEmployee)
log.Fatal(http.ListenAndServe(":8080", mux))
}
执行和测试步骤(假设你将上述代码保存为employee.go):
步骤1:运行命令 go run employee.go
步骤2:在浏览器中打开链接 http://localhost:8080/GetEmployee?memberId=123&activityType=Call&businessUnitCode=56
步骤3:你应该在浏览器窗口中看到以下响应:
{
"MemberId": "123",
"ActivityType": "Call",
"BusinessUnitCode": 56
}
步骤4:在控制台上你应该看到以下输出:
GET parameters: {123 Call 56}
英文:
Please find below the complete example of parsing get query params directly in a golang struct and then sending the struct back as response
package main
import (
"log"
"net/http"
"encoding/json"
"github.com/gorilla/schema"
)
var decoder = schema.NewDecoder()
type EmployeeStruct struct {
MemberId string `schema:"memberId"`
ActivityType string `schema:"activityType"`
BusinessUnitCode int `schema:"businessUnitCode"`
}
func GetEmployee(w http.ResponseWriter, r *http.Request) {
var employeeStruct EmployeeStruct
err := decoder.Decode(&employeeStruct, r.URL.Query())
if err != nil {
log.Println("Error in GET parameters : ", err)
} else {
log.Println("GET parameters : ", employeeStruct)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(employeeStruct)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/GetEmployee", GetEmployee)
log.Fatal(http.ListenAndServe(":8080", mux))
}
Steps to execute & Test (Assuming you are saving above code in employee.go) :
Step 1 : go run employee.go
Step 2 : Open in browser http://localhost:8080/GetEmployee?memberId=123&activityType=Call&businessUnitCode=56
Step 3 : You should get below response in browser window
{
"MemberId": "123",
"ActivityType": "Call",
"BusinessUnitCode": 56
}
Step 4 : On console you should see below
GET parameters : {123 Call 56}
答案2
得分: 3
示例:
filters={"reference":["docker.io/library/alpine:latest"]}
需要进行URL编码:
filters=%7B%22reference%22%3A%5B%22docker.io%2Flibrary%2Falpine%3Alatest%22%5D%7D
并且可以使用"github.com/gorilla/schema"
query := struct {
All bool
Filters map[string][]string `schema:"filters"`
Digests bool
Filter string
}{}
decoder := schema.NewDecoder()
decoder.Decode(&query, r.URL.Query())
英文:
example:
filters={"reference":["docker.io/library/alpine:latest"]}
need url encode to:
filters=%7B%22reference%22%3A%5B%22docker.io%2Flibrary%2Falpine%3Alatest%22%5D%7D
and could use "github.com/gorilla/schema"
query := struct {
All bool
Filters map[string][]string `schema:"filters"`
Digests bool
Filter string
}{}
decoder := schema.NewDecoder()
decoder.Decode(&query, r.URL.Query())
答案3
得分: 2
如@mh-cbon所指出的,gorilla schema是这里的终极解决方案。
而不是从URL属性中获取queryParams。
func handleRequest(w http.ResponseWriter, r *http.Request) {
queryString := r.URL.Query()
//...解析Values -> map[string][]string
}
gorilla schema的方法是将r.PostForm
传递给解码函数。
func handleRequest(w http.ResponseWriter, r *http.Request) {
err := decoder.Decode(person, r.PostForm)
//...使用反射可以调用每个结构体的属性,使用PostForm(url string, data url.Values)签名
fmt.Print(person.GoodJobGorilla)
}
英文:
As pointed out by @mh-cbon gorilla schema is the ultimate solution here.
Instead for obtaining the queryParams from the URL attribute.
func handleRequest(w http.ResponseWriter, r *http.Request) {
queryString := r.URL.Query()
//...parsing the Values -> map[string][]string
}
The approach of gorilla schema is to ship r.PostForm
to the decode function.
func handleRequest(w http.ResponseWriter, r *http.Request) {
err := decoder.Decode(person, r.PostForm)
//...using reflect each struct's property can be called using
// the PostForm(url string, data url.Values) signature
fmt.Print(person.GoodJobGorilla)
}
答案4
得分: 1
免责声明:我是这个包的创建者和维护者。
httpin帮助您轻松解码HTTP请求数据,包括:
- 查询参数,例如
?name=john&is_member=true
- 头部信息,例如
Authorization: xxx
- 表单数据,例如
username=john&password=******
- JSON/XML Body,例如
POST {"name":"john"}
- 路径变量,例如
/users/{username}
- 文件上传
如何使用?
type ListUsersInput struct {
Page int `in:"query=page"`
PerPage int `in:"query=per_page"`
IsMember bool `in:"query=is_member"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
if input.IsMember {
// Do sth.
}
// Do sth.
}
httpin具有以下特点:
- 文档完善:请参阅https://ggicci.github.io/httpin/
- 经过充分测试:覆盖率超过98%
- 开放集成:与net/http,go-chi/chi,gorilla/mux,gin-gonic/gin等集成
- 可扩展(高级功能):通过添加自定义指令。详细信息请阅读httpin - custom directives
- 被提及的很棒:https://github.com/avelino/awesome-go#forms
英文:
Using ggicci/httpin
Disclaimer: I'm the creator and maintainer of this package.
httpin helps you easily decoding HTTP request data from
- Query parameters, e.g.
?name=john&is_member=true
- Headers, e.g.
Authorization: xxx
- Form data, e.g.
username=john&password=******
- JSON/XML Body, e.g.
POST {"name":"john"}
- Path variables, e.g.
/users/{username}
- File uploads
How to use?
type ListUsersInput struct {
Page int `in:"query=page"`
PerPage int `in:"query=per_page"`
IsMember bool `in:"query=is_member"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
if input.IsMember {
// Do sth.
}
// Do sth.
}
httpin is:
- well documented: at https://ggicci.github.io/httpin/
- well tested: coverage over 98%
- open integrated: with net/http, go-chi/chi, gorilla/mux, gin-gonic/gin, etc.
- extensible (advanced feature): by adding your custom directives. Read httpin - custom directives for more details.
- awesome mentioned: https://github.com/avelino/awesome-go#forms
答案5
得分: 1
只需将字符串解析为URL,然后可以使用github.com/gorilla/schema
库进行解析
// 解析查询字符串到结构体的示例
package main
import (
"log"
"net/url"
"github.com/gorilla/schema"
)
type URLParams struct {
Code string `schema:"code"`
State string `schema:"state"`
}
func main() {
var (
params URLParams
decoder = schema.NewDecoder()
)
p := "https://www.redirect-url.com?code=CODE&state=RANDOM_ID"
u, _ := url.Parse(p)
err := decoder.Decode(¶ms, u.Query())
if err != nil {
log.Println("解码参数时出错:", err)
} else {
log.Printf("解码后的参数:%#v\n", params)
}
}
https://go.dev/play/p/CmuPhdKh6Yg
英文:
Just parse the string to URL and after you can use the lib github.com/gorilla/schema
to parse it
// Example to parse querystring to struct
package main
import (
"log"
"net/url"
"github.com/gorilla/schema"
)
type URLParams struct {
Code string `schema:"code"`
State string `schema:"state"`
}
func main() {
var (
params URLParams
decoder = schema.NewDecoder()
)
p := "https://www.redirect-url.com?code=CODE&state=RANDOM_ID"
u, _ := url.Parse(p)
err := decoder.Decode(&params, u.Query())
if err != nil {
log.Println("Error in Decode parameters : ", err)
} else {
log.Printf("Decoded parameters : %#v\n", params)
}
}
答案6
得分: 1
如果有人正在使用Echo,query
结构标签将对这种情况非常有用。
示例结构体
type struct Name {
FirstName string `query:"first_name"`
LastName string `query:"last_name"`
}
示例查询参数
?first_name="shahriar"&last_name="sazid"
代码
var name Name
err := c.Bind(&name); if err != nil {
return c.String(http.StatusBadRequest, "bad request")
}
英文:
If anyone is using Echo, query
struct tag will be useful for this case.
Example Struct
type struct Name {
FirstName string `query:"first_name"`
LastName string `query:"last_name"`
}
Example Query Param
?first_name="shahriar"&last_name="sazid"
Code
var name Name
err := c.Bind(&name); if err != nil {
return c.String(http.StatusBadRequest, "bad request")
}
答案7
得分: 0
你可以使用Echo的graceful包。
我写了一些代码作为示例,并添加了自解释的注释
package main
import (
"log"
"github.com/labstack/echo"
)
// 使用form:""标签声明你的结构体
type Employee struct {
MemberId string `form:"memberId"`
ActivityType string `form:"activityType"`
BusinessUnitCode int `form:"businessUnitCode"`
}
// 你的处理函数应该像这个方法一样
// 接收一个echo.Context并返回一个错误
func GetEmployee(ctx echo.Context) error {
var employee Employee
// 使用Bind方法,你可以从echo.Context中获取HTTP请求的Post Body或查询参数
if err := ctx.Bind(&employee); err != nil {
return err
}
// 现在你可以使用你的结构体,例如
return ctx.JSON(200, employee.MemberId)
}
// 现在在你的main函数或任何需要的地方使用处理函数
func main() {
e := echo.New()
e.GET("/employee", GetEmployee)
log.Fatal(e.Start(":8080"))
}
英文:
You can use the graceful package of Echo.
I write some codes as an example, with self-explanatory comments
package main
import (
"log"
"github.com/labstacks/echo"
)
// Declare your struct with form: "" tag
type Employee struct {
MemberId string `form:"memberId"`
ActivityType string `form:"activityType"`
BusinessUnitCode int `form:"businessUnitCode"`
}
// Your handlers should look like this method
// Which takes an echo.Context and returns an error
func GetEmployee(ctx echo.Context) error{
var employee Employee
// With Bind, you can get the Post Body or query params from http.Request
// that is wrapped by echo.Context here
if err := ctx.Bind(&employee);err != nil {
return err
}
// now you can use your struct , e.g
return ctx.json(200, employee.MemberId)
}
// now use the handler in your main function or anywhere you need
func main() {
e := echo.New()
e.Get("/employee", GetEmployee)
log.Fatal(e.Start(":8080"))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论