123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package dara
- import (
- "encoding/json"
- "errors"
- "fmt"
- "reflect"
- "regexp"
- "strconv"
- "strings"
- )
- type Model interface {
- Validate() error
- ToMap() map[string]interface{}
- copyWithouStream() Model
- }
- func Validate(params interface{}) error {
- if params == nil {
- return nil
- }
- requestValue := reflect.ValueOf(params)
- if requestValue.IsNil() {
- return nil
- }
- err := validate(requestValue.Elem())
- return err
- }
- // Verify whether the parameters meet the requirements
- func validate(dataValue reflect.Value) error {
- if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
- if dataValue.IsNil() {
- return nil
- }
- dataValue = dataValue.Elem()
- }
- dataType := dataValue.Type()
- for i := 0; i < dataType.NumField(); i++ {
- field := dataType.Field(i)
- valueField := dataValue.Field(i)
- for _, value := range validateParams {
- err := validateParam(field, valueField, value)
- if err != nil {
- return err
- }
- }
- }
- return nil
- }
- func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
- tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
- if containsTag && tagName == "require" {
- err := checkRequire(field, valueField)
- if err != nil {
- return err
- }
- }
- if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
- err := validateSlice(field, valueField, containsTag, tag, tagName)
- if err != nil {
- return err
- }
- } else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
- err := validatePtr(field, valueField, containsTag, tag, tagName)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
- if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
- if containsregexpTag {
- if tagName == "maxItems" {
- err := checkMaxItems(field, valueField, tag)
- if err != nil {
- return err
- }
- }
- if tagName == "minItems" {
- err := checkMinItems(field, valueField, tag)
- if err != nil {
- return err
- }
- }
- }
- for m := 0; m < valueField.Len(); m++ {
- elementValue := valueField.Index(m)
- if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
- err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
- if err != nil {
- return err
- }
- }
- }
- }
- return nil
- }
- func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
- if elementValue.IsNil() {
- return nil
- }
- if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
- if containsregexpTag {
- if tagName == "pattern" {
- err := checkPattern(field, elementValue.Elem(), tag)
- if err != nil {
- return err
- }
- }
- if tagName == "maxLength" {
- err := checkMaxLength(field, elementValue.Elem(), tag)
- if err != nil {
- return err
- }
- }
- if tagName == "minLength" {
- err := checkMinLength(field, elementValue.Elem(), tag)
- if err != nil {
- return err
- }
- }
- if tagName == "maximum" {
- err := checkMaximum(field, elementValue.Elem(), tag)
- if err != nil {
- return err
- }
- }
- if tagName == "minimum" {
- err := checkMinimum(field, elementValue.Elem(), tag)
- if err != nil {
- return err
- }
- }
- }
- } else {
- err := validate(elementValue)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func checkRequire(field reflect.StructField, valueField reflect.Value) error {
- name, _ := field.Tag.Lookup("json")
- strs := strings.Split(name, ",")
- name = strs[0]
- if !valueField.IsNil() && valueField.IsValid() {
- return nil
- }
- return errors.New(name + " should be setted")
- }
- func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() && valueField.String() != "" {
- value := valueField.String()
- r, _ := regexp.Compile("^" + tag + "$")
- if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
- return errors.New(value + " is not matched " + tag)
- }
- }
- return nil
- }
- func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() && valueField.String() != "" {
- maxItems, err := strconv.Atoi(tag)
- if err != nil {
- return err
- }
- length := valueField.Len()
- if maxItems < length {
- errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
- return errors.New(errMsg)
- }
- }
- return nil
- }
- func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() {
- minItems, err := strconv.Atoi(tag)
- if err != nil {
- return err
- }
- length := valueField.Len()
- if minItems > length {
- errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
- return errors.New(errMsg)
- }
- }
- return nil
- }
- func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() && valueField.String() != "" {
- maxLength, err := strconv.Atoi(tag)
- if err != nil {
- return err
- }
- length := valueField.Len()
- if valueField.Kind().String() == "string" {
- length = strings.Count(valueField.String(), "") - 1
- }
- if maxLength < length {
- errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
- return errors.New(errMsg)
- }
- }
- return nil
- }
- func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() {
- minLength, err := strconv.Atoi(tag)
- if err != nil {
- return err
- }
- length := valueField.Len()
- if valueField.Kind().String() == "string" {
- length = strings.Count(valueField.String(), "") - 1
- }
- if minLength > length {
- errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
- return errors.New(errMsg)
- }
- }
- return nil
- }
- func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() && valueField.String() != "" {
- maximum, err := strconv.ParseFloat(tag, 64)
- if err != nil {
- return err
- }
- byt, _ := json.Marshal(valueField.Interface())
- num, err := strconv.ParseFloat(string(byt), 64)
- if err != nil {
- return err
- }
- if maximum < num {
- errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
- return errors.New(errMsg)
- }
- }
- return nil
- }
- func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
- if valueField.IsValid() && valueField.String() != "" {
- minimum, err := strconv.ParseFloat(tag, 64)
- if err != nil {
- return err
- }
- byt, _ := json.Marshal(valueField.Interface())
- num, err := strconv.ParseFloat(string(byt), 64)
- if err != nil {
- return err
- }
- if minimum > num {
- errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
- return errors.New(errMsg)
- }
- }
- return nil
- }
|