Bind() is great, but what do you guys think if it supports default values when a param is not specified? Something like this:

    params = struct {
        Name string `form:"name,default=john"`
        Age uint `form:"address,default=10"`
    }{}

    c.Bind(&param)

Comment From: thinkerou

Hi @atedja I have commit one pull request and I attempt to complete it.

Comment From: thinkerou

@atedja Now the pr have merged to the master branch.

Comment From: appleboy

Implement in #1138 . try it in the latest master branch.

Comment From: calixwu

So, how to use it???

Comment From: KingJeason

So, how to use it ???

Comment From: to2false

@KingJeason @calixwu

`form:"field_name,default=value"`

It worked for me.

Comment From: calixwu

@to2false I have already used it that way, but thanks all the same. I think it's better to document this usage.

Comment From: SnowOnion

Another story. For those who, like me, want default JSON field value when using BindJSON: Just set the default value when initializing the struct. E.g.

params = struct {
    Name string `json:"name"`
    Age  uint   `json:"address"`
}{
    Name: "john",
    Age:  10,
}
c.BindJSON(&params)

And from this issue I got to know anonymous struct.

I learnt a lot today.

Comment From: Gera-coder

Another story. For those who, like me, want default JSON field value when using BindJSON: Just set the default value when initializing the struct. E.g.

go params = struct { Name string `json:"name"` Age uint `json:"address"` }{ Name: "john", Age: 10, } c.BindJSON(&params)

And from this issue I got to know anonymous struct.

I learnt a lot today.

Hi Snow, I tried your way but it can only work with field missing. For example, if you passed in a json string with age set to init value zero, 10 would got replaced.

Comment From: kamly

@thinkerou @SnowOnion @Gera-coder

I want to wirte this

type Param struct {
   Name string `json:"name,default=john"`
   Age uint `json:"address,default=10"`
}
var param Param
c.ShouldBind(&param)

but it doesn't work, has any good method in ShouldBind JSON?

Comment From: runzhliu

I think the default value doesn't work for the json type, actually, I find no related unitest for the default value except for the form type, but assigning the default value before the binding works for me.

Comment From: kangour

if use dive then default invalid, help.

Comment From: olivatooo

help :pensive:

Comment From: AuroraTea

@KingJeason @calixwu

`form:"field_name,default=value"`

It worked for me.

Sorry for Interrupting you, is it now discarded?

type ReqListUsers struct {
    Limit  int64  `form:"limit,default=20" binding:"min=1,max=100"`
    Sort   string `form:"sort,default=id" binding:"omitempty,oneof=id createAt lastLoginAt"`
    Order  string `form:"order,default=asc" binding:"omitempty,oneof=asc desc"`
}

func ListUsers(c *gin.Context) {
    var req ReqListUsers
    err := c.ShouldBindQuery(&req)

But not work.

Comment From: hexuan1922

@thinkerou @SnowOnion @Gera-coder

I want to wirte this

go type Param struct { Name string `json:"name,default=john"` Age uint `json:"address,default=10"` } var param Param c.ShouldBind(&param)

but it doesn't work, has any good method in ShouldBind JSON?


type User struct {
    Name string `form:"name,default=user1" json:"name,default=user2"`
    Age  int    `form:"age,default=10" json:"age,default=20"`
}

r := gin.Default()

// way1 curl 127.0.0.1:8900/bind?name=aa
// way2 curl -X POST 127.0.0.1:8900/bind -d "name=aa&age=30"
// way3 curl -X POST 127.0.0.1:8900/bind -H "Content-Type: application/json" -d "{\"name\": \"aa\"}"
r.Any("/bind", func(c *gin.Context) {
    var user User
    //user = User{Name: "bb", Age: 11} //way4:A variable of type User can be generated with the default value before bind

    if c.ContentType() == binding.MIMEJSON {
        //way5:A variable of type User can be generated with the default value before bind.
        _ = binding.MapFormWithTag(&user, nil, "json")
    }

    _ = c.Bind(&user) //Note that because bind is used here to request json, you specify the Content-Type header
    c.String(200, "Hello %v age %v", user.Name, user.Age)
})

// The above 4 way.
// way1/2 structTag is work.because gin at queryBinding/formBinding execute mapFormByTag logic, will check formTag
// way3 structTag not work. gin at jsonBinding non-execution  mapFormByTag logic
// way4/way5 no matter query/form/json All valid
// way5 is work.  Because the mapFormByTag logic is triggered in addition

r.Run(":8900")

good luck. @kamly

Comment From: kangour

楼上通过 _ = binding.MapFormWithTag(&user, nil, "json") 修改参数的解析 tag,对我有效,感谢分享。

Comment From: cylonchau

@hexuan1922 I use github.com/gin-gonic/gin v1.10.0 and use your example, but following code don't work, just can work on single struct.

type Target struct {
    metav1.TypeMeta
    Targets          []TargetItem      `form:"targets" json:"targets"`
    InstanceSelector map[string]string `json:"instanceSelector"`
}

type TargetItem struct {
    Address       string            `form:"address" json:"address" yaml:"address"  binding:"required"`
    MetricPath    string            `form:"metric_path,default=/metrics" json:"metric_path,default=/metrics" yaml:"metric_path"`
    ScrapeTime    int               `form:"scrap_time,default=30" json:"scrape_time,default=30" yaml:"scrap_time" `
    ScrapeTimeout int               `form:"scrape_timeout,default=10" json:"scrape_timeout,default=10" yaml:"scrap_timeout"`
    Labels        map[string]string `json:"labels,omitempty" yaml:"labels,omitempty" form:"labels,omitempty"`
}
    var enconterError error
    targetQuery := &target.Target{}

    _ := binding.MapFormWithTag(&targetQuery, nil, "json")

    if enconterError = c.Bind(&targetQuery); enconterError != nil {
        query.API500Response(c, enconterError)
        return
    }
    fmt.Println(targetQuery)

targetQuery.Targets is a list, and inital, it is a nil, the targetQuery don't kown amount of targetQuery.Targets, so this code don't work.

if execute MapFormWithTag() after execute Bind(), then value will be overwrite with default tag, despite passing in a value instead of using the default.

Comment From: cylonchau

楼上通过 _ = binding.MapFormWithTag(&user, nil, "json") 修改参数的解析 tag,对我有效,感谢分享。

这种方式只是在初始化这个结构体时,手动映射一下tag,然后再Bind时,如果传入了参数会被重写,没有传入就使用默认值了,这种情况只能是使用非列表类型时生效,如果你的参数结构体使用了列表类型,初始binding.MapFormWithTag不知道列表数量,他不会进行重写,而且嵌套格式通常无法指定tag,所以这种方式不会应用子结构体中的tag或者列表中的tag

Comment From: AtariOverlord09

@KingJeason @calixwu `form:"field_name,default=value"`

It worked for me.

Sorry for Interrupting you, is it now discarded?

``go type ReqListUsers struct { Limit int64form:"limit,default=20" binding:"min=1,max=100"Sort stringform:"sort,default=id" binding:"omitempty,oneof=id createAt lastLoginAt"Order stringform:"order,default=asc" binding:"omitempty,oneof=asc desc"` }

func ListUsers(c *gin.Context) { var req ReqListUsers err := c.ShouldBindQuery(&req) ```

But not work.

how did you fix it?