...

Source file src/github.com/go-playground/validator/v10/struct_level.go

Documentation: github.com/go-playground/validator/v10

     1  package validator
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  )
     7  
     8  // StructLevelFunc accepts all values needed for struct level validation
     9  type StructLevelFunc func(sl StructLevel)
    10  
    11  // StructLevelFuncCtx accepts all values needed for struct level validation
    12  // but also allows passing of contextual validation information via context.Context.
    13  type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)
    14  
    15  // wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx
    16  func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx {
    17  	return func(ctx context.Context, sl StructLevel) {
    18  		fn(sl)
    19  	}
    20  }
    21  
    22  // StructLevel contains all the information and helper functions
    23  // to validate a struct
    24  type StructLevel interface {
    25  
    26  	// Validator returns the main validation object, in case one wants to call validations internally.
    27  	// this is so you don't have to use anonymous functions to get access to the validate
    28  	// instance.
    29  	Validator() *Validate
    30  
    31  	// Top returns the top level struct, if any
    32  	Top() reflect.Value
    33  
    34  	// Parent returns the current fields parent struct, if any
    35  	Parent() reflect.Value
    36  
    37  	// Current returns the current struct.
    38  	Current() reflect.Value
    39  
    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 its kind.
    43  	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
    44  
    45  	// ReportError reports an error just by passing the field and tag information
    46  	//
    47  	// NOTES:
    48  	//
    49  	// fieldName and altName get appended to the existing namespace that
    50  	// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending
    51  	// on the nesting
    52  	//
    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)
    56  
    57  	// ReportValidationErrors reports an error just by passing ValidationErrors
    58  	//
    59  	// NOTES:
    60  	//
    61  	// relativeNamespace and relativeActualNamespace get appended to the
    62  	// existing namespace that validator is on.
    63  	// e.g. 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 current field depth
    66  	ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
    67  }
    68  
    69  var _ StructLevel = new(validate)
    70  
    71  // Top returns the top level struct
    72  //
    73  // NOTE: this can be the same as the current struct being validated
    74  // if not is a nested struct.
    75  //
    76  // this is only called when within Struct and Field Level validation and
    77  // should not be relied upon for an accurate value otherwise.
    78  func (v *validate) Top() reflect.Value {
    79  	return v.top
    80  }
    81  
    82  // Parent returns the current structs parent
    83  //
    84  // NOTE: this can be the same as the current struct being validated
    85  // if not is a nested struct.
    86  //
    87  // this is only called when within Struct and Field Level validation and
    88  // should not be relied upon for an accurate value otherwise.
    89  func (v *validate) Parent() reflect.Value {
    90  	return v.slflParent
    91  }
    92  
    93  // Current returns the current struct.
    94  func (v *validate) Current() reflect.Value {
    95  	return v.slCurrent
    96  }
    97  
    98  // Validator returns the main validation object, in case one want to call validations internally.
    99  func (v *validate) Validator() *Validate {
   100  	return v.v
   101  }
   102  
   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)
   106  }
   107  
   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) {
   110  
   111  	fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
   112  
   113  	if len(structFieldName) == 0 {
   114  		structFieldName = fieldName
   115  	}
   116  
   117  	v.str1 = string(append(v.ns, fieldName...))
   118  
   119  	if v.v.hasTagNameFunc || fieldName != structFieldName {
   120  		v.str2 = string(append(v.actualNs, structFieldName...))
   121  	} else {
   122  		v.str2 = v.str1
   123  	}
   124  
   125  	if kind == reflect.Invalid {
   126  
   127  		v.errs = append(v.errs,
   128  			&fieldError{
   129  				v:              v.v,
   130  				tag:            tag,
   131  				actualTag:      tag,
   132  				ns:             v.str1,
   133  				structNs:       v.str2,
   134  				fieldLen:       uint8(len(fieldName)),
   135  				structfieldLen: uint8(len(structFieldName)),
   136  				param:          param,
   137  				kind:           kind,
   138  			},
   139  		)
   140  		return
   141  	}
   142  
   143  	v.errs = append(v.errs,
   144  		&fieldError{
   145  			v:              v.v,
   146  			tag:            tag,
   147  			actualTag:      tag,
   148  			ns:             v.str1,
   149  			structNs:       v.str2,
   150  			fieldLen:       uint8(len(fieldName)),
   151  			structfieldLen: uint8(len(structFieldName)),
   152  			value:          fv.Interface(),
   153  			param:          param,
   154  			kind:           kind,
   155  			typ:            fv.Type(),
   156  		},
   157  	)
   158  }
   159  
   160  // ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
   161  //
   162  // NOTE: this function prepends the current namespace to the relative ones.
   163  func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {
   164  
   165  	var err *fieldError
   166  
   167  	for i := 0; i < len(errs); i++ {
   168  
   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...))
   172  
   173  		v.errs = append(v.errs, err)
   174  	}
   175  }
   176  

View as plain text