-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Cross Field OR validation #195
Comments
Currently there are no built in tags to do Cross Field OR validation. once getting into situations like you defined above, I consider them to be complex validation rules that even if built in tags could be used, it would become very hard to read. But the library has a an easy reusable way to achieve what you want by creating a custom validation function, and then you may use and reuse it as a tag in your structs. Example// define funciton
func oneFieldSet(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
// use topStruct instead of currentStructOrField below if want function to be able to do cross struct cross field validation
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
if !ok || currentKind != fieldKind {
return false
}
// if field has a value, just like the hasValue function then return true
// if currentField has a value return true
// return false by default
}
validate := //new validator
validate.RegisterValidation("eitherrequired", oneFieldSet)
type User struct {
Username string `validate:"eitherrequired=Email"`
Email string `validate:"eitherrequired=Username"`
} then you could reuse this tag/validation function in a bunch of your structs Does that make sense? P.S. you gave me a great idea, that I should expose the existing validators so that you can use them inside custom ones; then you could use hasValue ( which is the function that "required" tag runs ) in your custom function. |
Hey @scisci I've updated validator to expose the baked in functions for use within custom functions, so below is a more complete example using the exposed functions. Example// define funciton
func oneFieldSet(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
// use topStruct instead of currentStructOrField below if want function to be able to do cross struct cross field validation
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
if !ok || currentKind != fieldKind {
return false
}
if validator.HasValue(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
return true
}
if validator.HasValue(v, topStruct, currentStructOrField, currentField, fieldType, currentKind, param) {
return true
}
return false
}
validate := //new validator
validate.RegisterValidation("eitherrequired", oneFieldSet)
type User struct {
Username string `validate:"eitherrequired=Email"`
Email string `validate:"eitherrequired=Username"`
} will this work for your needs? it should be generic enough to use within many of your structs |
awesome! yeah that totally works for me. I will look into implementing it as soon as possible. thanks @joeybloggs I had some more complex validation as well so using a validation function makes total sense. |
perfect! glad I could help @scisci if you need any help or have any question, just let me know. |
Hey @scisci thought I'd let you know about Struct Level Validations see here: https://github.com/go-playground/validator/releases/tag/v8.7 this may be an even better way to do your username or email check 😄 |
Is it possible to validate that on a given struct at least one of two options is required? I often have a struct where as long as one out of 2 of the fields are filled in, it will pass validation. One basic example would be having a username field and an email field (just a basic example though).
The text was updated successfully, but these errors were encountered: