required_without doesn't seem to work with multiple fields
Package version eg. v8, v9:
Package version v9
Issue, Question or Enhancement:
In this example, I would expect validation to succeed, but it doesn't despite all the required_without fields being present.
Code sample, to showcase or reproduce:
https://play.golang.org/p/O9CuEA2aOFr
Hey @fizzy123 this will work if you use required_without_all it looks like some of the docs have been copy-pasted and are not 100% correct.
I could use some help with that if you have some time :)
I just got bit w/ this too :smiley:
help with docs
So, am I right in thinking that required_without_all is the plural/list version of required_without, i.e. If you want to have a list of Fields to check against you must use the "_all" version?
It looks that way from my tests but thought I'd ask before I go too deep into the rabbit hole.
Also, are these the docs you refer too? https://github.com/go-playground/validator/blob/0ab8e0351d0126a6c1325b8df8cd4fa06a13e229/doc.go#L293
Cheers 👍
I'm having the same problem:
type Settings struct {
Opt, Val string
}
cc := struct {
Model string
Value string
Settings *Settings `validate:"required_without_all=Model Value"`
}{
Model: "foo",
// Value: "bar",
}
validate := validator.New()
err := validate.Struct(cc)
fmt.Println(err)
This should imho error but doesn't. My expectation for string was
- must exist (in case of pointer to string)
- must not be empty (
"")
Could you kindly clarify what the expected required behaviour depending on type is?
I'd be happy in contributing to the docs (or making doc.go more visible), but I'm still struggling with how it's supposed to work.
See examples from the docs:
// require the field if the Field1 is not present:
Usage: required_without=Field1
// require the field if the Field1 or Field2 is not present:
Usage: required_without=Field1 Field2
Yes it says "or". I've tried that multiple fields value, same as @fizzy123, but it doesn't work :frowning_face:
To achieve that "or" validation, here's what I do:
required_without=Field1,required_without=Field2
@yaliv reading the play from @fizzy123 the requirement is for validation to fail when all fields are empty. Your suggestion is the same as the play and imho works when any of the fields are empty. The way to go is required_without_all as @deankarn wrote. Unfortunately it seems as if required_without_all doesn't fully work as expected.
@andig I don't think so.
@fizzy123 wrote in the playground:
- Field1
validate:"required_without=Field2 Field3 Field4" - Then he filled out Field2, Field3, Field4.
So the expected result is: If Field2 or Field3 or Field4 is not present, then Field1 is required. He filled out all those 3 fields, so Field1 is not required. But it's not: "Field1 is still required"
Now let's compare it with required_without_all.
See example from the docs:
// require the field if the Field1 and Field2 is not present:
Usage: required_without_all=Field1 Field2
If we modify the validation above:
- Field1
validate:"required_without_all=Field2 Field3 Field4"
The expected result is: If Field2 and Field3 and Field4 are not present, then Field1 is required. Meaning that all those 3 fields have to be empty for Field1 to be required.
If any of those 3 fields has value, then Field1 is not required.
I've tried both scenarios. "without all = all empty" --> it works :+1: "without = any empty" --> it doesn't work :-1:
Indeed, some of the docs are not 100% correct. And we can see what's actually done by those 2 validators: https://github.com/go-playground/validator/blob/v9.31.0/baked_in.go#L1384-L1403
But I hope this library has 3 types of required validation:
without= one field emptywithout_all= all fields emptywithout_any= any field empty
As I said before, the current workaround for without_any ("or" validation) is like this one:
required_without=Field1,required_without=Field2
In the play, fields 2..4 are populated. Field 1 should never throw a validation error regardless if without or without_all is used, yet it does. If you see my issue above you‘ll see another problem with the logic- also without_all seems to error (or rather not error) when it should. Imho there is something wrong with the without* validations.
@andig let's try both validators right in the playground:
- Field1
validate:"required_without=Field2 Field3 Field4"--> result:Key: 'a.Field1' Error:Field validation for 'Field1' failed on the 'required_without' tag - Field1
validate:"required_without_all=Field2 Field3 Field4"--> result:Test B OK
Furthermore, let's stay with the required_without_all validator and modify the struct value:
a{Field2: testInt}--> result:Test B OKa{}--> result:Key: 'a.Field1' Error:Field validation for 'Field1' failed on the 'required_without_all' tag
That's because required_without_all only triggers error when all mentioned fields are empty.
Now let's talk about your example code.
If you don't fill any fields like this:
cc := struct {
Model string
Value string
Settings *Settings `validate:"required_without_all=Model Value"`
}{}
you'll get an error: Key: 'Settings' Error:Field validation for 'Settings' failed on the 'required_without_all' tag
Field Settings is required when all mentioned fields are empty. Same as my explanation above.
If you fill Model, then Settings is not required.
If you fill Value, then Settings is not required too.
There's nothing wrong with this validator :wink:
@yaliv you are right. Thank you for correcting my mistake. I really appreciate your feedback.
There is still something wrong with require_without, please see https://play.golang.org/p/ljheF_I2uwN:
s := struct {
Field1 string `validate:"required_without=Field2"`
Field2 string `validate:"required_without=Field1"`
}{
Field1: "Field1",
}
This should error on Field1 but doesn't?
s := struct { Field1 string `validate:"required_without=Field2"` Field2 string `validate:"required_without=Field1"` }{ Field1: "Field1", }This should error on
Field1but doesn't?
Nope, that's fine.
I do the same. See mine:
type Auth struct {
APIKey string `json:"apiKey" validate:"required_without=Username,required_without=Password"`
Username string `json:"username" validate:"required_without=APIKey"`
Password string `json:"password" validate:"required_without=APIKey"`
}
From the data flow perspective, I actually don't need any validations here, because:
- None of the fields is "always" required.
- The next step, I still need to make sure that
APIKeyhas value before using it, otherwise I'll be usingUsernameandPassword.
But there are still advantages of setting validations here:
- Assume that there's no guarantee that the checking will be done in the next step. Here is the best place to set validations.
- The error message will be uniform with any other validations.
As you can see above, it's currently the best way I can write the validations.
If Username or Password is empty, I'll get an error. But before that happen, I fill out APIKey and it's fine, validation passed :heavy_check_mark:
Hi,
Just checking if this was fixed already, or planned to be fixed?
Here is another simple example that fails:
type MyStruct struct {
Field1 *a validate:"required_without=Field3 Field2"
Field2 *b
Field3 *b
}
type a struct { Aa string }
type b struct { Bb string }
https://go.dev/play/p/kOF6ROYXlw1
Will be happy if this would be solved.
Thanks.