reproduce

func TestBinding(t *testing.T) {
    type MyRequest struct {
        Config map[string]string `form:"config" binding:"required"`
        App    int               `form:"app" binding:"required"`
    }
    r := gin.Default()
    r.POST("/test", func(c *gin.Context) {
        var sss MyRequest
        fmt.Println(c.Request.Header.Get("Content-Type"))
        fmt.Println(c.PostForm("config[c1]"))
        fmt.Println(c.PostFormMap("config"))
        c.ShouldBind(&sss)
        fmt.Println(sss)
        c.JSON(200, gin.H{
            "message": sss,
        })
    })
    r.Run(":8080")
}

result

application/x-www-form-urlencoded;charset=UTF-8
1
map[c1:1 c2:2]
{map[] 3}

And I also tested form.NewDecoder() simultaneously, and it worked correctly.

go 1.21.1 gin version 1.9.1

Comment From: shawn1251

The ShouldBind method in Gin doesn't directly support binding to a map. As an alternative, you can use the PostFormMap method to obtain the map from the form data and then assign it to the respective field in your struct. Here's an example:

var conf map[string]string
conf = c.PostFormMap("config")
fmt.Println(conf)
c.ShouldBind(&sss)
sss.Config = conf

This approach allows you to manually extract the map from the form data and then assign it to the desired field in your struct.