gin icon indicating copy to clipboard operation
gin copied to clipboard

Get request, unable to get multidimensional array parameters

Open fancyecommerce opened this issue 6 years ago • 6 comments

// trace info
type TraceInfo struct{
    Id_ bson.ObjectId `form:"_id" json:"_id" bson:"_id"` 
    Search SearchInfo `form:"search" json:"search" bson:"search"`
}

// search
type SearchInfo struct{
    Text string `form:"text" json:"text" bson:"text"`
    ResultQty string `form:"result_qty" json:"result_qty" bson:"result_qty"`
}

func SaveJsData(c *gin.Context){
    var traceInfo TraceInfo
    err := c.ShouldBindQuery(&traceInfo);
    if err != nil {
        c.AbortWithStatusJSON(http.StatusOK, util.BuildFailResult(err.Error()))
        return
    }
}

when i access http://xxxx:3000/fec/trace?search[text]=dress&search[result_qty]=13

can not get this search param,empty:

 "search": {
     "text": "",
     "result_qty": "" 
  } 

fancyecommerce avatar Apr 10 '18 02:04 fancyecommerce

AFAIK, Go does not support nested form parameters like it does with JSON/XML. This is due to the form/query object simply being a map[string][]string. So if you run the example below, you'll see what i'm talking about.

package main

import (
	"github.com/gin-gonic/gin"
)

func handler(c *gin.Context) {
	if err := c.Request.ParseForm(); err != nil {
		c.AbortWithStatusJSON(400, gin.H{"error": err.Error()})
		return
	}

	c.JSON(200, gin.H{
		"query": c.Request.URL.Query(),
		"form":  c.Request.Form,
	})
}

func main() {
	router := gin.Default()
	router.Any("/test", handler)
	router.Run(":5000")
}

Then in the browser visit http://localhost:5000/test?name=bob&info[foo]=bar. Example output:

{
  "form": {
    "info[foo]": [
      "bar"
    ],
    "name": [
      "bob"
    ]
  },
  "query": {
    "info[foo]": [
      "bar"
    ],
    "name": [
      "bob"
    ]
  }
}

sosedoff avatar Apr 12 '18 21:04 sosedoff

@fancyecommerce please see https://github.com/gin-gonic/gin#bind-form-data-request-with-custom-struct, maybe it can help you.

thinkerou avatar May 16 '18 12:05 thinkerou

I am having a similar issue where ShouldBindQuery does not seem to recognize the "comma pattern" in the query part of the url such as ?genre=jazz,blues.

Gin version: 1.6.3

For example, if I request the following

$ curl http://localhost:8082/rest/v1/search\?genre\=jazz,blues

with the following code

type searchQuery struct {
	Genre                 []string `form:"genre"`
}

func searchHandler(c *gin.Context) {
         var query searchQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		log.Fatal(err)
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
        genre := c.Request.URL.Query()
        log.Printf("genre %v, length %d, searchQuery.Genre %v, length %d, type  %T", genre["genre"], len(genre["genre"]), query.Genre, len(query.Genre), query.Genre)
}

the app logs

// -> Genre [jazz,blues], length 1, searchQuery.Genre [jazz,blues], length 1, type []string

If I deduplicate the query params as in

$ curl http://localhost:8082/rest/v1/search\?genre\=jazz\&genre\=blues

the app logs

// -> Genre [jazz blues], length 2, searchQuery.Genre [jazz blues], length 2, type []string

and works. I am not sure what I am doing wrong, but it feels kinda odd.

andreacab avatar May 20 '20 17:05 andreacab

hey I am facing same problem. were you able to resolve yours? having to duplicate query params doesn't look clean to me. comma separated values seem simple and cleaner. any pointers please? @thinkerou @appleboy

rexfordnyrk avatar Jul 08 '20 11:07 rexfordnyrk

Hey guys, it turns out to be easier than it seemed, see the example here:

type FilterData struct {
  RegionId uint8      `query:"regionId"`
  Phone    string     `query:"phone"`
}

type Filter struct {
  Data     FilterData `query:"data"`
}

type Payload struct {
  Filter   Filter     `query:"filter"`
}

func getAnnounce(c *gin.Context) {
  // ?filter[data][regionId]=1&filter[data][phone]=380001234567
  Url.UnmarshalQuery(c.Request.URL.Query(), &payload)
})

yukal avatar Sep 25 '23 13:09 yukal

I am having a similar issue where ShouldBindQuery does not seem to recognize the "comma pattern" in the query part of the url such as ?genre=jazz,blues.

Gin version: 1.6.3

For example, if I request the following

$ curl http://localhost:8082/rest/v1/search\?genre\=jazz,blues

with the following code

type searchQuery struct {
	Genre                 []string `form:"genre"`
}

func searchHandler(c *gin.Context) {
         var query searchQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		log.Fatal(err)
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
        genre := c.Request.URL.Query()
        log.Printf("genre %v, length %d, searchQuery.Genre %v, length %d, type  %T", genre["genre"], len(genre["genre"]), query.Genre, len(query.Genre), query.Genre)
}

the app logs

// -> Genre [jazz,blues], length 1, searchQuery.Genre [jazz,blues], length 1, type []string

If I deduplicate the query params as in

$ curl http://localhost:8082/rest/v1/search\?genre\=jazz\&genre\=blues

the app logs

// -> Genre [jazz blues], length 2, searchQuery.Genre [jazz blues], length 2, type []string

and works. I am not sure what I am doing wrong, but it feels kinda odd.

Seem this issue still exists. I wonder why the maintainers not address this.

katatrina avatar Aug 02 '24 03:08 katatrina