Hi guys. I have the following problem

type Foo struct {
    Bar bool `json:"bar" binding:"required"` // True / False
}

When I send a JSON request with the value true it works, but when I send the same request with false I get the following error.

{
    "error": {
        "Foo.Bar": {
            "FieldNamespace": "Foo.Bar",
                "NameNamespace": "Bar",
            "Field": "Bar",
            "Name": "Bar",
            "Tag": "required",
            "ActualTag": "required",
            "Kind": 1,
            "Type": {},
            "Param": "",
            "Value": false
        }
    }
},

Comment From: deankarn

I'll refer you to:

685

611

In summary you need a pointer or custom type to know if the value exists due to Go's static nature.

Comment From: appleboy

Change bool to *bool

Comment From: bardia-key

Just an update to whomever is still stuck with this bug. Addind *bool is not the entire solution. You must change the binding:"required" to binding:"exists".

Here is the documentation to back that up (gin uses this pkg for input obj validations): https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Exists

Comment From: deankarn

Thanks @bkeyoumarsi

to further this answer exists was removed in v9 and required works with *bool

I highly recommend updating to v9, there were many performance updates and changes for ease of use :)

see https://github.com/go-playground/validator/tree/v9/examples/gin-upgrading-overriding for updating gin to use v9 of validator.

Comment From: EsonChurch

wtf

Comment From: sawtamlahtoo

man fuck this shit

Comment From: rickyManalo

This seems to still be happening. I already have the latest version and added both * and binding:"required" to the field and the field is still not getting returned

UPDATE: It seems my issue wasn't caused by gin itself, but because of the generated files of protobuf adding omitempty on all fields

Comment From: cohendvir

here too :/

Comment From: matisiekpl

Is there any update here? Adding ,omitempty still does not fix the bug 😢

Comment From: appleboy

@matisiekpl What is your problem? I think the comment can fix the issue.

Comment From: forbesd7

This is my understanding for why we use *bool rather than bool to anyone who might be wondering:

Golang gives booleans a default value of 'false' so if a value in JSON has 'false' there isn't a way to differentiate between the default value and an actual false value. So by using a pointer we can differentiate between the default value of '&false' and nil (default value for unset pointer)

With *Bool

type Todo struct {
    Done *bool `json:"done" binding:"required"`
}

// These JSON inputs would result in:
{"done": true}   -> Done: &true
{"done": false}  -> Done: &false
{}               -> Done: nil

With Bool

type Todo struct {
    Done bool `json:"done" binding:"required"`
}

// These JSON inputs would result in:
{"done": true}   -> Done: true
{"done": false}  -> Done: false
{}               -> Done: false  // (default/zero value)

Please let me know if this understanding is wrong/misleading :) @appleboy @deankarn