Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to validate bool #142

Closed
davisford opened this issue Aug 3, 2015 · 32 comments
Closed

How to validate bool #142

davisford opened this issue Aug 3, 2015 · 32 comments
Assignees
Labels
Milestone

Comments

@davisford
Copy link

type Thing struct {
  Truthiness bool `json:"truthiness" validate:"required"`
}

Using gin-gonic/gin with this, when it marshals JSON into a struct, this passes:

{ "truthiness": true }

But this fails, b/c it is the golang zero-value for bool

{ "truthiness": false }

I just want to validate that the property exists -- if it exists, I know it will have a value of true or false.

Nothing obvious popped out at me from: https://godoc.org/gopkg.in/bluesuncorp/validator.v5#pkg-variables

@deankarn
Copy link
Contributor

deankarn commented Aug 3, 2015

I think there may be some small confusion about how this works.

Validator validates the data within the struct after it has been in unmarshalled from JSON.

So the steps that happen are:

  • JSON post received
  • during Bind the struct is initialized
  • the JSON is unmarshalled into the structure variables

Since go is statically typed, regardless if truthiness is passed or not, the structure will always have a value and since go's bool's are not tri-state.

It does not validate the JSON but data after unmarshalling.

Sorry for no samples, answering from my phone.
Doe's this answer your question?

@deankarn deankarn self-assigned this Aug 3, 2015
@deankarn deankarn added this to the v5 milestone Aug 3, 2015
@deankarn
Copy link
Contributor

deankarn commented Aug 3, 2015

Give me a few minutes, I have an idea that may work for you.

Just tied up at the moment

@deankarn
Copy link
Contributor

deankarn commented Aug 3, 2015

I was thinking you could make the bool value a pointer, then it would fail when no value was present, but it would still fail ifvaluewas false so that won't work.

I may look into adding a new tag, "exists" it will not have any validation functions associated with it, however will be the failure tag when value is a pointer and is value of nil.

In the mean time however, there really isn't a way to check if a bool is set.

@davisford
Copy link
Author

I was going to maybe take a stab at writing a custom validator that could just check if something exists, but I figured I'd ask here first in case I misread the situation.

@deankarn
Copy link
Contributor

deankarn commented Aug 4, 2015

I'm actually in the middle of adding the "exists" tag it's seem to work well when using bool as a pointer, will let you know when it's released; hopefully tonight.

@davisford
Copy link
Author

Awesome! thanks!

@deankarn
Copy link
Contributor

deankarn commented Aug 4, 2015

Hey @davisford, guess I was closer than I though lol

Example

if you use "exists" tag like below and bool is a pointer you will get the functionality you are looking for.
NOTE: this works with any Pointer, Interface or Invalid Type.

type Thing struct {
  Truthiness *bool `json:"truthiness" validate:"exists"`
}

Notes

This change was implemented in v6 and back-ported to v5.

I Highly recommend everyone to update to v6 if possible as some things added in v6 already cannot be back-ported to v5 due to the code change between v5 and v6

UPDATE: Please let me know if this works as expected for you and I can close this issue

@davisford
Copy link
Author

Awesome -- thank you. I may have to make my own fork of gin and update to v6. Might take a bit -- sounds like you tested it out...feel free to close the issue. I appreciate the super immediate response time.

@deankarn
Copy link
Contributor

deankarn commented Aug 4, 2015

no problems, yes I tested with your exact scenario with bool as a pointer and using exists flag.

P.S. @davisford I think gin allows for custom/other validation libraries to be plugged in, in this case just the updated version, however I don't have a link to the commit, or documentation.

P.P.S star if you like, just trying to get more stars than the other validators out there, even ones that are unmaintained have more stars 😦

@deankarn deankarn closed this as completed Aug 4, 2015
@deankarn
Copy link
Contributor

deankarn commented Aug 5, 2015

Hey @davisford I came across how to add your own validator in gin to avoid forking, it's in this issue 2nd or 3rd comment gin-gonic/gin#224 (comment)

@0x7061
Copy link

0x7061 commented Sep 28, 2016

Is this still supported in v9 ? I need the same behaviour for HTTP PATCH where I have to distinguish between ommited and set values - therefore the bool pointer. I'm getting the error that exists does not exist as a validator.

EDIT: I found the exists validator in v8 - works like a charm there! No idea where it went in v9 lol.

@deankarn
Copy link
Contributor

Hey @codepushr I dropped exists in favour of just using required and added some nullable checks so required should work just like exists did in this scenario.

if not then it could be a bug, could you provide some sample code and I'll check it out ASAP

@0x7061
Copy link

0x7061 commented Sep 28, 2016

Sure! This should demonstrate what I mean. Basically the validation fails although I'm using a pointer to a bool with false as the value. What I'm expecting is that if I use a pointer the validation only checks if it's not nil - but in this case it also checks the underlying value - which MAY work as expected but is different from exists in v8.

package main

import (
    "log"

    v "gopkg.in/go-playground/validator.v9"
)

type Foo struct {
    Bar *bool `validate:"required"`
}

func main() {
    b := false

    model := Foo{
        Bar: &b,
    }

    err := v.New().Struct(model)

    log.Println(err)
}

@deankarn
Copy link
Contributor

Hey @codepushr thanks for the code,

I already replicated the issue, just running last minute tests and fix will be out in a few minutes so required will now work as expected.

will tag you and this issue when making the final release.

P.S. thanks for reporting.

@deankarn
Copy link
Contributor

ok @codepushr release 9.2.0 should fix this for you.

Please let me know if it works for you 😃

NOTE: the reason I removed exists is that required implies exists and had a number of people mention that it was confusing and so now required handles both, with one tag.

@0x7061
Copy link

0x7061 commented Sep 28, 2016

@joeybloggs Looking good! Thanks for the amazingly quick response! :)

@FrankHitman
Copy link

thanks all

@lucassimon
Copy link

package todos

import (
	"time"

	"github.com/go-playground/validator/v10"
)

// Todo This is a model for TODO
type Todo struct {
	ID        string    `json:"id"`
	Name      string    `json:"name" validate:"required"`
	Completed bool      `json:"completed" validate:"required"`
	CreatedAt time.Time `json:"created_at"`
}

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

// Validate validate input data
func (t *Todo) Validate() error {
	validate := validator.New()
	return validate.Struct(t)
}

Payload:

{
	"name": "Teste",
	"completed": false
}

Response message:

{
  "error": "Key: 'Todo.Completed' Error:Field validation for 'Completed' failed on the 'required' tag"
}

Source: https://github.com/lucassimon/fiber-estudos

@SokratisVidros
Copy link

Same issue as the above. Could you suggest the best solution for v10?

@thalesfsp
Copy link

Reopened in #714.

@ricardojonathanromero
Copy link

ricardojonathanromero commented Feb 9, 2021

model

 type Toggle struct {
	Status *bool `json:"status" validate:"required"`
}

func for validate

func validateRequest(c echo.Context, payload interface{}) error {
	c.Echo().Validator = &models.Validator{Validator: validator.New()}

	if err := c.Bind(payload); err != nil {
		s.Log.Errorf("Invalid request. c.Bind() => %s", err.Error())
		return err
	}

	if err := c.Validate(payload); err != nil {
		s.Log.Errorf("Invalid request. c.Validate() => %s, \terror: %s", StructToString(payload), err.Error())
		return err
	}

	return nil
}

and it works. To validate if bool exists, you need to make bool as a pointer.

Note: I tested it in v9

@wstiehler
Copy link

wstiehler commented Dec 13, 2021

Good morning guys. Same problem as in v10 with Bool equal to false. Even passing in the request body, it returns that it is necessary to pass. Any suggestion?

image
image

@KanzakiRanko1
Copy link

Good morning guys. Same problem as in v10 with Bool equal to false. Even passing in the request body, it returns that it is necessary to pass. Any suggestion?

image image

Running v10.9.0 and having the same issue.

@harezmii
Copy link

harezmii commented Jan 4, 2022

Status *bool , If the bool value is set to a pointer, the error is fixed. Version 10.10.0

@encryptblockr
Copy link

@harezmii

Status *bool , If the bool value is set to a pointer, the error is fixed. Version 10.10.0

getting this error

cannot use data.IsWrite (type *bool) as type bool in field value

@Faridalim
Copy link

*bool still doesn't work for me. Any ideas to solve this guys?

@EduFrazao
Copy link

Same problem here guys. Version v10.11.1:

type BaseMaterialData struct {
	Name        string `json:"name" validate:"required,max=125"`
	Description string `json:"description" validate:"max=256"`
	Active      bool   `json:"active" validate:"required"`
}

When a json with "active: false" arrives, validator fails.

@Faridalim
Copy link

@EduFrazao try remove required, set default value to false

@EduFrazao
Copy link

@EduFrazao try remove required, set default value to false

Thanks. I've done that as a workaround and its running.

@brnocorreia
Copy link

@EduFrazao try remove required, set default value to false

Hi, man! Can u show me how u did that? I'm experiencing the same error but cant change my type to *bool

@nsmosi
Copy link

nsmosi commented Aug 12, 2023

if you use

Active      bool   `json:"active" validate:"required"`

and if the payload send json {"active": false} then it will not pass the validation , but if payload send as json {"active": true} then it will pass the validation, which in both case should pass. I tried it like so:

Active      bool   `json:"active" validate:"required,boolean"` 

the same

I tried it like so:

Active      bool   `json:"active" validate:"boolean"`

it works, but when payload does not contain the active then no error occurs which is still not correct

This is my validator version:
"github.com/go-playground/validator/v10"

@deankarn
Copy link
Contributor

@nsmosi this has been explained many times in a number of issues. I believe it is a misunderstanding of how Go works.

as defined on your struct is a bool which has two states true and false. In go there is no such thing as an uninitialized variable and so if the value is not defined in the JSON it will be false by default on your struct.

if false being the default state if not in the JSON is desired then theres really no need to validate it at all.

if you need to detect presence then you need a third state. Changing to a pointer *bool is one way to give this third state to ensure it was set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests