github.com/alibabacloud-go/tea@v1.3.10/dara/model.go (about)

     1  package dara
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  	"regexp"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  type Model interface {
    14  	Validate() error
    15  	ToMap() map[string]interface{}
    16  	copyWithouStream() Model
    17  }
    18  
    19  func Validate(params interface{}) error {
    20  	if params == nil {
    21  		return nil
    22  	}
    23  	requestValue := reflect.ValueOf(params)
    24  	if requestValue.IsNil() {
    25  		return nil
    26  	}
    27  	err := validate(requestValue.Elem())
    28  	return err
    29  }
    30  
    31  // Verify whether the parameters meet the requirements
    32  func validate(dataValue reflect.Value) error {
    33  	if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
    34  		if dataValue.IsNil() {
    35  			return nil
    36  		}
    37  		dataValue = dataValue.Elem()
    38  	}
    39  	dataType := dataValue.Type()
    40  	for i := 0; i < dataType.NumField(); i++ {
    41  		field := dataType.Field(i)
    42  		valueField := dataValue.Field(i)
    43  		for _, value := range validateParams {
    44  			err := validateParam(field, valueField, value)
    45  			if err != nil {
    46  				return err
    47  			}
    48  		}
    49  	}
    50  	return nil
    51  }
    52  
    53  func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
    54  	tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
    55  	if containsTag && tagName == "require" {
    56  		err := checkRequire(field, valueField)
    57  		if err != nil {
    58  			return err
    59  		}
    60  	}
    61  	if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
    62  		err := validateSlice(field, valueField, containsTag, tag, tagName)
    63  		if err != nil {
    64  			return err
    65  		}
    66  	} else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
    67  		err := validatePtr(field, valueField, containsTag, tag, tagName)
    68  		if err != nil {
    69  			return err
    70  		}
    71  	}
    72  	return nil
    73  }
    74  
    75  func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
    76  	if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
    77  		if containsregexpTag {
    78  			if tagName == "maxItems" {
    79  				err := checkMaxItems(field, valueField, tag)
    80  				if err != nil {
    81  					return err
    82  				}
    83  			}
    84  
    85  			if tagName == "minItems" {
    86  				err := checkMinItems(field, valueField, tag)
    87  				if err != nil {
    88  					return err
    89  				}
    90  			}
    91  		}
    92  
    93  		for m := 0; m < valueField.Len(); m++ {
    94  			elementValue := valueField.Index(m)
    95  			if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
    96  				err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
    97  				if err != nil {
    98  					return err
    99  				}
   100  			}
   101  		}
   102  	}
   103  	return nil
   104  }
   105  
   106  func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
   107  	if elementValue.IsNil() {
   108  		return nil
   109  	}
   110  	if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
   111  		if containsregexpTag {
   112  			if tagName == "pattern" {
   113  				err := checkPattern(field, elementValue.Elem(), tag)
   114  				if err != nil {
   115  					return err
   116  				}
   117  			}
   118  
   119  			if tagName == "maxLength" {
   120  				err := checkMaxLength(field, elementValue.Elem(), tag)
   121  				if err != nil {
   122  					return err
   123  				}
   124  			}
   125  
   126  			if tagName == "minLength" {
   127  				err := checkMinLength(field, elementValue.Elem(), tag)
   128  				if err != nil {
   129  					return err
   130  				}
   131  			}
   132  
   133  			if tagName == "maximum" {
   134  				err := checkMaximum(field, elementValue.Elem(), tag)
   135  				if err != nil {
   136  					return err
   137  				}
   138  			}
   139  
   140  			if tagName == "minimum" {
   141  				err := checkMinimum(field, elementValue.Elem(), tag)
   142  				if err != nil {
   143  					return err
   144  				}
   145  			}
   146  		}
   147  	} else {
   148  		err := validate(elementValue)
   149  		if err != nil {
   150  			return err
   151  		}
   152  	}
   153  	return nil
   154  }
   155  
   156  func checkRequire(field reflect.StructField, valueField reflect.Value) error {
   157  	name, _ := field.Tag.Lookup("json")
   158  	strs := strings.Split(name, ",")
   159  	name = strs[0]
   160  	if !valueField.IsNil() && valueField.IsValid() {
   161  		return nil
   162  	}
   163  	return errors.New(name + " should be setted")
   164  }
   165  
   166  func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
   167  	if valueField.IsValid() && valueField.String() != "" {
   168  		value := valueField.String()
   169  		r, _ := regexp.Compile("^" + tag + "$")
   170  		if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
   171  			return errors.New(value + " is not matched " + tag)
   172  		}
   173  	}
   174  	return nil
   175  }
   176  
   177  func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
   178  	if valueField.IsValid() && valueField.String() != "" {
   179  		maxItems, err := strconv.Atoi(tag)
   180  		if err != nil {
   181  			return err
   182  		}
   183  		length := valueField.Len()
   184  		if maxItems < length {
   185  			errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
   186  			return errors.New(errMsg)
   187  		}
   188  	}
   189  	return nil
   190  }
   191  
   192  func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
   193  	if valueField.IsValid() {
   194  		minItems, err := strconv.Atoi(tag)
   195  		if err != nil {
   196  			return err
   197  		}
   198  		length := valueField.Len()
   199  		if minItems > length {
   200  			errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
   201  			return errors.New(errMsg)
   202  		}
   203  	}
   204  	return nil
   205  }
   206  
   207  func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
   208  	if valueField.IsValid() && valueField.String() != "" {
   209  		maxLength, err := strconv.Atoi(tag)
   210  		if err != nil {
   211  			return err
   212  		}
   213  		length := valueField.Len()
   214  		if valueField.Kind().String() == "string" {
   215  			length = strings.Count(valueField.String(), "") - 1
   216  		}
   217  		if maxLength < length {
   218  			errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
   219  			return errors.New(errMsg)
   220  		}
   221  	}
   222  	return nil
   223  }
   224  
   225  func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
   226  	if valueField.IsValid() {
   227  		minLength, err := strconv.Atoi(tag)
   228  		if err != nil {
   229  			return err
   230  		}
   231  		length := valueField.Len()
   232  		if valueField.Kind().String() == "string" {
   233  			length = strings.Count(valueField.String(), "") - 1
   234  		}
   235  		if minLength > length {
   236  			errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
   237  			return errors.New(errMsg)
   238  		}
   239  	}
   240  	return nil
   241  }
   242  
   243  func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
   244  	if valueField.IsValid() && valueField.String() != "" {
   245  		maximum, err := strconv.ParseFloat(tag, 64)
   246  		if err != nil {
   247  			return err
   248  		}
   249  		byt, _ := json.Marshal(valueField.Interface())
   250  		num, err := strconv.ParseFloat(string(byt), 64)
   251  		if err != nil {
   252  			return err
   253  		}
   254  		if maximum < num {
   255  			errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
   256  			return errors.New(errMsg)
   257  		}
   258  	}
   259  	return nil
   260  }
   261  
   262  func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
   263  	if valueField.IsValid() && valueField.String() != "" {
   264  		minimum, err := strconv.ParseFloat(tag, 64)
   265  		if err != nil {
   266  			return err
   267  		}
   268  
   269  		byt, _ := json.Marshal(valueField.Interface())
   270  		num, err := strconv.ParseFloat(string(byt), 64)
   271  		if err != nil {
   272  			return err
   273  		}
   274  		if minimum > num {
   275  			errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
   276  			return errors.New(errMsg)
   277  		}
   278  	}
   279  	return nil
   280  }