8 // StructLevelFunc accepts all values needed for struct level validation
9 type StructLevelFunc func(sl StructLevel)
11 // StructLevelFuncCtx accepts all values needed for struct level validation
12 // but also allows passing of contextual validation information vi context.Context.
13 type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)
15 // wrapStructLevelFunc wraps noramal StructLevelFunc makes it compatible with StructLevelFuncCtx
16 func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx {
17 return func(ctx context.Context, sl StructLevel) {
22 // StructLevel contains all the information and helper functions
23 // to validate a struct
24 type StructLevel interface {
26 // returns the main validation object, in case one want to call validations internally.
27 // this is so you don;t have to use anonymous functoins to get access to the validate
31 // returns the top level struct, if any
34 // returns the current fields parent struct, if any
35 Parent() reflect.Value
37 // returns the current struct.
38 Current() reflect.Value
40 // ExtractType gets the actual underlying type of field value.
41 // It will dive into pointers, customTypes and return you the
42 // underlying value and it's kind.
43 ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
45 // reports an error just by passing the field and tag information
49 // fieldName and altName get appended to the existing namespace that
50 // validator is on. eg. pass 'FirstName' or 'Names[0]' depending
53 // tag can be an existing validation tag or just something you make up
54 // and process on the flip side it's up to you.
55 ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
57 // reports an error just by passing ValidationErrors
61 // relativeNamespace and relativeActualNamespace get appended to the
62 // existing namespace that validator is on.
63 // eg. pass 'User.FirstName' or 'Users[0].FirstName' depending
64 // on the nesting. most of the time they will be blank, unless you validate
65 // at a level lower the the current field depth
66 ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
69 var _ StructLevel = new(validate)
71 // Top returns the top level struct
73 // NOTE: this can be the same as the current struct being validated
74 // if not is a nested struct.
76 // this is only called when within Struct and Field Level validation and
77 // should not be relied upon for an acurate value otherwise.
78 func (v *validate) Top() reflect.Value {
82 // Parent returns the current structs parent
84 // NOTE: this can be the same as the current struct being validated
85 // if not is a nested struct.
87 // this is only called when within Struct and Field Level validation and
88 // should not be relied upon for an acurate value otherwise.
89 func (v *validate) Parent() reflect.Value {
93 // Current returns the current struct.
94 func (v *validate) Current() reflect.Value {
98 // Validator returns the main validation object, in case one want to call validations internally.
99 func (v *validate) Validator() *Validate {
103 // ExtractType gets the actual underlying type of field value.
104 func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
105 return v.extractTypeInternal(field, false)
108 // ReportError reports an error just by passing the field and tag information
109 func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {
111 fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
113 if len(structFieldName) == 0 {
114 structFieldName = fieldName
117 v.str1 = string(append(v.ns, fieldName...))
119 if v.v.hasTagNameFunc || fieldName != structFieldName {
120 v.str2 = string(append(v.actualNs, structFieldName...))
125 if kind == reflect.Invalid {
127 v.errs = append(v.errs,
134 fieldLen: uint8(len(fieldName)),
135 structfieldLen: uint8(len(structFieldName)),
143 v.errs = append(v.errs,
150 fieldLen: uint8(len(fieldName)),
151 structfieldLen: uint8(len(structFieldName)),
152 value: fv.Interface(),
160 // ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
162 // NOTE: this function prepends the current namespace to the relative ones.
163 func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {
167 for i := 0; i < len(errs); i++ {
169 err = errs[i].(*fieldError)
170 err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
171 err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))
173 v.errs = append(v.errs, err)