I'm honestly not sure whether or not it is the intended behavior or a bug, but here it goes:
type MyRequestStruct struct {
PropertyOne string `json:"propertyOne" binding:"required"`
PropertyTwo string `json:"propertyTwo" binding:"required"`
}
func main() {
engine := gin.New()
engine.POST("/test", func (ctx *gin.Context) {
var req MyRequestStruct
if err := ctx.BindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, err)
} else {
ctx.JSON(http.StatusOK, req)
}
})
engine.Run("localhost:8080")
}
So I have tested with these 3 requests. For me only the last one should fail.
1 -
curl -X POST http://localhost:8080/test -d '{ "propertyOne": "1", "propertyTwo": "2" }' -H "Content-Type: application/json"
Respone:
{
"propertyOne": "1",
"propertyTwo": "2"
}
2 -
curl -X POST http://localhost:8080/test -d '{ "propertyOne": "", "propertyTwo": "" }' -H "Content-Type: application/json"
Response:
{
"MyRequestStruct.PropertyOne": {
"FieldNamespace": "MyRequestStruct.PropertyOne",
"NameNamespace": "PropertyOne",
"Field": "PropertyOne",
"Name": "PropertyOne",
"Tag": "required",
"ActualTag": "required",
"Kind": 24,
"Type": {},
"Param": "",
"Value": ""
},
"MyRequestStruct.PropertyTwo": {
"FieldNamespace": "MyRequestStruct.PropertyTwo",
"NameNamespace": "PropertyTwo",
"Field": "PropertyTwo",
"Name": "PropertyTwo",
"Tag": "required",
"ActualTag": "required",
"Kind": 24,
"Type": {},
"Param": "",
"Value": ""
}
}
3 -
curl -X POST http://localhost:8080/test -d '{ }' -H "Content-Type: application/json"
Returns:
{
"MyRequestStruct.PropertyOne": {
"FieldNamespace": "MyRequestStruct.PropertyOne",
"NameNamespace": "PropertyOne",
"Field": "PropertyOne",
"Name": "PropertyOne",
"Tag": "required",
"ActualTag": "required",
"Kind": 24,
"Type": {},
"Param": "",
"Value": ""
},
"MyRequestStruct.PropertyTwo": {
"FieldNamespace": "MyRequestStruct.PropertyTwo",
"NameNamespace": "PropertyTwo",
"Field": "PropertyTwo",
"Name": "PropertyTwo",
"Tag": "required",
"ActualTag": "required",
"Kind": 24,
"Type": {},
"Param": "",
"Value": ""
}
}
I guess it's intended to work this way. The validation runs on the struct after unmarshalling the request body. It doesn't check the body and can't verify if a value is empty or missing.
that's exactly correct @stxml because of go's static nature it will always have value, think of required as nondefault instead.
but if you really need to check if there is any value you do have options, you can set your strings fields to be pointers to string *string and instead of using required can use the exists tag instead.
@deankarn I encountered the same problem even though I set all parameters with a value and strings fields also set to be pointers.
Most helpful comment
that's exactly correct @stxml because of go's static nature it will always have value, think of
requiredasnondefaultinstead.but if you really need to check if there is any value you do have options, you can set your strings fields to be pointers to string
*stringand instead of usingrequiredcan use theexiststag instead.