go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.98k stars 1.33k forks source link

Support for mutually exclusive groups of validations chained with OR #1280

Open adam-shamaa opened 5 months ago

adam-shamaa commented 5 months ago

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

I'd like to defined groups of validations from existing rules and chain them together with an OR clause. Something along the lines of

var req struct {
    Email string `validate:"(bakedin_tag1,bakedin_tag2)|bakedin_tag3"`
}

The syntax above of using parentheses/brackets isn't supported so I've tried defining an alias for the (bakedin_tag_1, bakedin_tag_2) clause:

validate.RegisterAlias("lcase_email", "email,lowercase")

However, there's a bug where aliases can't be used with an OR operator (existing issue for this https://github.com/go-playground/validator/issues/766)

Seem like the only route would be avoiding an alias and defining a custom validator function which validates the email and lowercase rule. But I want to avoid this as I'd be re-creating the baked-in validation methods isEmail and isLowerCase https://github.com/go-playground/validator/blob/a947377040f8ebaee09f20d09a745ec369396793/baked_in.go#L1675-L1678 https://github.com/go-playground/validator/blob/a947377040f8ebaee09f20d09a745ec369396793/baked_in.go#L2707-L2719 As these methods are private to the validator package so I can't reference them.

Code sample, to showcase or reproduce:

package main

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

type Example struct {
    Email string `validate:"lcase_email|empty_string"`
}

func main() {
    validate := validator.New()
    validate.RegisterAlias("lcase_email", "email,lowercase")
    validate.RegisterAlias("empty_string", "eq=")

    ex := &Example{
        Email: "badger.smith@gmail.com",
    }

    err := validate.Struct(ex)
    if err != nil {
        println(err.Error())
    }
}