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 }