如何将所有GET请求查询参数放入Go中的结构体中?

2024-05-23

你好,我想将 get 查询参数转换为 Go 中的结构,例如我有这样的结构:

type Filter struct {
    Offset int64  `json:"offset"`
    Limit  int64  `json:"limit"`
    SortBy string `json:"sortby"`
    Asc    bool   `json:"asc"`

    //User specific filters
    Username   string `json:"username"`
    First_Name string `json:"first_name"`
    Last_Name  string `json:"last_name"`
    Status     string `json:"status"`
}

我有用户在发送 get 请求时可以指定的可选参数,它们是Offset, Limit, SortBy, Asc, Username, First_Name, Last_Name, Status.

如果这些参数是在正文中发送的,那么我会这样做:

b, err := ioutil.ReadAll(r.Body)
if err != nil {

    log.WithFields(logFields).Errorf("Reading Body Message:failed:%v", err)

    return
}

var filter Filter
err = json.Unmarshal(b, &filter)

但我无法将正文发送到GET请求那么解决方案是什么,而不是单独获取每个参数然后将它们放入结构中?


使用大猩猩的schema package

The github.com/gorilla/schema http://www.gorillatoolkit.org/pkg/schemapackage正是为此而发明的。

您可以使用结构标签 https://stackoverflow.com/questions/10858787/what-are-the-uses-for-tags-in-go/30889373#30889373告诉如何将 URL 参数映射到结构体字段,schema包寻找"schema"标签键。

使用它:

import "github.com/gorilla/schema"

type Filter struct {
    Offset int64  `schema:"offset"`
    Limit  int64  `schema:"limit"`
    SortBy string `schema:"sortby"`
    Asc    bool   `schema:"asc"`

    //User specific filters
    Username   string `schema:"username"`
    First_Name string `schema:"first_name"`
    Last_Name  string `schema:"last_name"`
    Status     string `schema:"status"`
}

func MyHandler(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        // Handle error
    }

    filter := new(Filter)
    if err := schema.NewDecoder().Decode(filter, r.Form); err != nil {
        // Handle error
    }

    // Do something with filter
    fmt.Printf("%+v", filter)
}

使用编组和解组json

请注意,schema包还将尝试将参数值转换为字段的类型。

如果该结构仅包含以下字段[]string类型(或者你愿意做出妥协),你可以做到这一点,而无需schema包裹。

Request.Form https://golang.org/pkg/net/http/#Request is a map,映射自string to []string(因为一个参数可能会在 URL 中多次列出:

Form url.Values

And url.Values https://golang.org/pkg/net/url/#Values:

type Values map[string][]string

例如,如果您的Filter结构看起来像这样:

type Filter struct {
    Offset []string `json:"offset"`
    Limit  []string `json:"limit"`
    SortBy []string `json:"sortby"`
    // ..other fields
}

你可以简单地使用json https://golang.org/pkg/encoding/json/包到编组r.Form,然后将其解组到您的结构中:

func MyHandler(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        // Handle error
    }
    data, err := json.Marshal(r.Form)
    if err != nil {
        // Handle error
    }
    filter := new(Fiter)
    if err = json.Unmarshal(data, filter); err != nil {
        // Handle error
    }
    fmt.Printf("%+v", filter)
}

此解决方案处理是否为同一参数名称提供多个值。如果你不关心多个值而只想要一个,那么你首先必须“转换”r.Form to a map与单string值而不是[]string.

它可能是这样的:

type Filter struct {
    Offset string `json:"offset"`
    Limit  string `json:"limit"`
    SortBy string `json:"sortby"`
    // ..other fields
}

// Transformation from map[string][]string to map[string]string:
m := map[string]string{}
for k, v := range r.Form {
    m[k] = v[0]
}

然后你就可以编组m并将其解组到Filter以同样的方式构造。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将所有GET请求查询参数放入Go中的结构体中? 的相关文章

随机推荐