Validator: Cross Field OR validation

Created on 15 Oct 2015  路  5Comments  路  Source: go-playground/validator

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).

question

Most helpful comment

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 :smile:

All 5 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 :smile:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexyans picture alexyans  路  3Comments

puellanivis picture puellanivis  路  5Comments

0505gonzalez picture 0505gonzalez  路  3Comments

Jake-Convictional picture Jake-Convictional  路  4Comments

phenrigomes picture phenrigomes  路  5Comments