• gin version (or commit ref): 1.3.0
  • operating system: Linux

Description

How does the function BindQuery bind the array? type DeleteQueryParam struct { UserName int form:"name" binding:"required" ttl string form:"ttl" binding:"required" Id []int form:"id" binding:"required" } param id can't bind the array correctly Gin c.BindQuery how can bind array query?

Comment From: thinkerou

@younglifestyle please see #653 issue BTW, you should search issue or pull request when answer question before. thanks!

Comment From: swrap

Gin version: v1.4.0 OS: Linux

@thinkerou referenced both #653 and #570. Maybe I am doing something wrong, but there are no concrete examples anywhere.

Description

Make a request with an array of form values will be parsed correctly as a list.

Replication

Request: https://www.example.com/publish?ids[]=16&ids[]=18&isPublished=true

Gin Backend:

func checkIfPublished(c *gin.Context) {
    type queryHolder struct {
        IsPublished bool   `form:"isPublished" binding:"exists"`
        Ids         []uint `form:"ids[]" binding:"required"`
    }
    var qholder queryHolder
    if err := c.ShouldBindQuery(&qholder); err != nil {
        c.AbortWithStatus(http.StatusBadRequest)
        return
    }
    log.Printf("%+v\n", qholder)
}

Output:

2019/10/20 16:09:34 {IsPublished:true Ids:[18]}

Expected Output

2019/10/20 16:09:34 {IsPublished:true Ids:[16,18]}

Comment From: vkd

For me everything is ok:

2019/10/20 21:11:47 {IsPublished:true Ids:[16 18]}
[GIN] 2019/10/20 - 21:11:47 | 200 |     433.233µs |             ::1 | GET      /hello?ids[]=16&ids[]=18&isPublished=true
curl -i "http://localhost:9000/hello?ids\[\]=16&ids\[\]=18&isPublished=true"
HTTP/1.1 200 OK

Comment From: swrap

For me everything is ok:

2019/10/20 21:11:47 {IsPublished:true Ids:[16 18]} [GIN] 2019/10/20 - 21:11:47 | 200 | 433.233µs | ::1 | GET /hello?ids[]=16&ids[]=18&isPublished=true

curl -i "http://localhost:9000/hello?ids\[\]=16&ids\[\]=18&isPublished=true" HTTP/1.1 200 OK

@vkd You were completely right so sorry about this. It was because I had my endpoint behind AWS gateway, which it does not support duplicates.

Comment From: breemts

Does anyone have an idea what the struct tag syntax for this array format could look like? Because this call is not working:

curl -i "http://localhost:9000/hello?ids=16,18&isPublished=true"

Also the following request does not result in an error, but should in my opinion:

curl -i "http://localhost:9000/hello?isPublished=true&ids\[\]="

will result in the output: {IsPublished:true Ids:[0]}

Comment From: louis77

AFAIK Gin doesn't support binding of comma-separated values into slices. But you can build your own type:

type CSIntList string

func (c CSIntList) Values() []int {
    res := []int{}

    str := string(c)
    if len(str) > 0 {
        values := strings.Split(str, ",")
        for _, v := range values {
            if i, err := strconv.Atoi(v); err == nil {
                res = append(res, i)
            }
        }
    }

    if len(res) == 0 {
        return nil
    }
    return res
}

type queryHolder struct {
    IsPublished bool   `form:"isPublished" binding:"exists"`
    Ids         CSIntList `form:"ids" binding:"required"`
}


...
... := gin.Bind(&query)
ids := query.Ids.Values()
...