model.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. package dara
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. )
  11. type Model interface {
  12. Validate() error
  13. ToMap() map[string]interface{}
  14. copyWithouStream() Model
  15. }
  16. func Validate(params interface{}) error {
  17. if params == nil {
  18. return nil
  19. }
  20. requestValue := reflect.ValueOf(params)
  21. if requestValue.IsNil() {
  22. return nil
  23. }
  24. err := validate(requestValue.Elem())
  25. return err
  26. }
  27. // ValidateRequired checks if a value is set (non-nil)
  28. func ValidateRequired(value interface{}, fieldName string) error {
  29. if value == nil {
  30. return errors.New(fieldName + " should be setted")
  31. }
  32. // Check for typed nil pointers
  33. switch v := value.(type) {
  34. case *string:
  35. if v == nil {
  36. return errors.New(fieldName + " should be setted")
  37. }
  38. case *int:
  39. if v == nil {
  40. return errors.New(fieldName + " should be setted")
  41. }
  42. case *int8:
  43. if v == nil {
  44. return errors.New(fieldName + " should be setted")
  45. }
  46. case *int16:
  47. if v == nil {
  48. return errors.New(fieldName + " should be setted")
  49. }
  50. case *int32:
  51. if v == nil {
  52. return errors.New(fieldName + " should be setted")
  53. }
  54. case *int64:
  55. if v == nil {
  56. return errors.New(fieldName + " should be setted")
  57. }
  58. case *uint:
  59. if v == nil {
  60. return errors.New(fieldName + " should be setted")
  61. }
  62. case *uint8:
  63. if v == nil {
  64. return errors.New(fieldName + " should be setted")
  65. }
  66. case *uint16:
  67. if v == nil {
  68. return errors.New(fieldName + " should be setted")
  69. }
  70. case *uint32:
  71. if v == nil {
  72. return errors.New(fieldName + " should be setted")
  73. }
  74. case *uint64:
  75. if v == nil {
  76. return errors.New(fieldName + " should be setted")
  77. }
  78. case *float32:
  79. if v == nil {
  80. return errors.New(fieldName + " should be setted")
  81. }
  82. case *float64:
  83. if v == nil {
  84. return errors.New(fieldName + " should be setted")
  85. }
  86. }
  87. return nil
  88. }
  89. // ValidateMaxLength validates maximum length using type assertions
  90. func ValidateMaxLength(value interface{}, maxLength int, fieldName string) error {
  91. length := getValueLength(value)
  92. if length > maxLength {
  93. return fmt.Errorf("The length of %s is %d which is more than %d", fieldName, length, maxLength)
  94. }
  95. return nil
  96. }
  97. // ValidateMinLength validates minimum length using type assertions
  98. func ValidateMinLength(value interface{}, minLength int, fieldName string) error {
  99. length := getValueLength(value)
  100. if length < minLength {
  101. return fmt.Errorf("The length of %s is %d which is less than %d", fieldName, length, minLength)
  102. }
  103. return nil
  104. }
  105. // ValidatePattern validates string against regex pattern
  106. func ValidatePattern(value interface{}, pattern string, fieldName string) error {
  107. strValue := getStringValue(value)
  108. if strValue == "" {
  109. return nil // Empty strings are valid unless required
  110. }
  111. r, err := regexp.Compile("^" + pattern + "$")
  112. if err != nil {
  113. return err
  114. }
  115. if !r.MatchString(strValue) {
  116. return errors.New(strValue + " is not matched " + pattern)
  117. }
  118. return nil
  119. }
  120. // ValidateMaximum validates maximum value for numeric types
  121. func ValidateMaximum(value interface{}, maximum float64, fieldName string) error {
  122. numValue, ok := getNumericValue(value)
  123. if !ok {
  124. return nil // Skip validation for non-numeric types
  125. }
  126. if numValue > maximum {
  127. return fmt.Errorf("The size of %s is %f which is greater than %f", fieldName, numValue, maximum)
  128. }
  129. return nil
  130. }
  131. // ValidateMinimum validates minimum value for numeric types
  132. func ValidateMinimum(value interface{}, minimum float64, fieldName string) error {
  133. numValue, ok := getNumericValue(value)
  134. if !ok {
  135. return nil // Skip validation for non-numeric types
  136. }
  137. if numValue < minimum {
  138. return fmt.Errorf("The size of %s is %f which is less than %f", fieldName, numValue, minimum)
  139. }
  140. return nil
  141. }
  142. // ValidateArray validates array/slice elements recursively
  143. func ValidateArray(arr interface{}, validator func(interface{}) error) error {
  144. switch v := arr.(type) {
  145. case []interface{}:
  146. for _, item := range v {
  147. if err := validator(item); err != nil {
  148. return err
  149. }
  150. }
  151. case []*string:
  152. for _, item := range v {
  153. if err := validator(item); err != nil {
  154. return err
  155. }
  156. }
  157. case []*int:
  158. for _, item := range v {
  159. if err := validator(item); err != nil {
  160. return err
  161. }
  162. }
  163. // Add more specific types as needed
  164. }
  165. return nil
  166. }
  167. // ValidateMap validates map values recursively
  168. func ValidateMap(m interface{}, validator func(interface{}) error) error {
  169. switch v := m.(type) {
  170. case map[string]interface{}:
  171. for _, value := range v {
  172. if err := validator(value); err != nil {
  173. return err
  174. }
  175. }
  176. case map[string]*string:
  177. for _, value := range v {
  178. if err := validator(value); err != nil {
  179. return err
  180. }
  181. }
  182. // Add more specific types as needed
  183. }
  184. return nil
  185. }
  186. // Helper functions using pure type assertions (no reflection)
  187. // getStringValue extracts string value using type assertions
  188. func getStringValue(value interface{}) string {
  189. switch v := value.(type) {
  190. case string:
  191. return v
  192. case *string:
  193. if v != nil {
  194. return *v
  195. }
  196. return ""
  197. default:
  198. return ""
  199. }
  200. }
  201. // getNumericValue extracts numeric value as float64 using type assertions
  202. func getNumericValue(value interface{}) (float64, bool) {
  203. switch v := value.(type) {
  204. // Direct numeric types
  205. case int:
  206. return float64(v), true
  207. case int8:
  208. return float64(v), true
  209. case int16:
  210. return float64(v), true
  211. case int32:
  212. return float64(v), true
  213. case int64:
  214. return float64(v), true
  215. case uint:
  216. return float64(v), true
  217. case uint8:
  218. return float64(v), true
  219. case uint16:
  220. return float64(v), true
  221. case uint32:
  222. return float64(v), true
  223. case uint64:
  224. return float64(v), true
  225. case float32:
  226. return float64(v), true
  227. case float64:
  228. return v, true
  229. // Pointer types
  230. case *int:
  231. if v != nil {
  232. return float64(*v), true
  233. }
  234. case *int8:
  235. if v != nil {
  236. return float64(*v), true
  237. }
  238. case *int16:
  239. if v != nil {
  240. return float64(*v), true
  241. }
  242. case *int32:
  243. if v != nil {
  244. return float64(*v), true
  245. }
  246. case *int64:
  247. if v != nil {
  248. return float64(*v), true
  249. }
  250. case *uint:
  251. if v != nil {
  252. return float64(*v), true
  253. }
  254. case *uint8:
  255. if v != nil {
  256. return float64(*v), true
  257. }
  258. case *uint16:
  259. if v != nil {
  260. return float64(*v), true
  261. }
  262. case *uint32:
  263. if v != nil {
  264. return float64(*v), true
  265. }
  266. case *uint64:
  267. if v != nil {
  268. return float64(*v), true
  269. }
  270. case *float32:
  271. if v != nil {
  272. return float64(*v), true
  273. }
  274. case *float64:
  275. if v != nil {
  276. return *v, true
  277. }
  278. default:
  279. return 0, false
  280. }
  281. return 0, false
  282. }
  283. // getValueLength returns length of string, array, slice, or map using type assertions
  284. func getValueLength(value interface{}) int {
  285. switch v := value.(type) {
  286. case string:
  287. // Use the same method as original implementation for consistency
  288. return len([]rune(v))
  289. case *string:
  290. if v != nil {
  291. return len([]rune(*v))
  292. }
  293. return 0
  294. case []interface{}:
  295. return len(v)
  296. case []string:
  297. return len(v)
  298. case []*string:
  299. return len(v)
  300. case []int:
  301. return len(v)
  302. case []*int:
  303. return len(v)
  304. case map[string]interface{}:
  305. return len(v)
  306. case map[string]string:
  307. return len(v)
  308. case map[string]*string:
  309. return len(v)
  310. // Add more specific types as needed
  311. default:
  312. return 0
  313. }
  314. }
  315. // Deprecated: use new validation methods instead
  316. // Verify whether the parameters meet the requirements
  317. func validate(dataValue reflect.Value) error {
  318. if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
  319. if dataValue.IsNil() {
  320. return nil
  321. }
  322. dataValue = dataValue.Elem()
  323. }
  324. dataType := dataValue.Type()
  325. for i := 0; i < dataType.NumField(); i++ {
  326. field := dataType.Field(i)
  327. valueField := dataValue.Field(i)
  328. for _, value := range validateParams {
  329. err := validateParam(field, valueField, value)
  330. if err != nil {
  331. return err
  332. }
  333. }
  334. }
  335. return nil
  336. }
  337. func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
  338. tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
  339. if containsTag && tagName == "require" {
  340. err := checkRequire(field, valueField)
  341. if err != nil {
  342. return err
  343. }
  344. }
  345. if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
  346. err := validateSlice(field, valueField, containsTag, tag, tagName)
  347. if err != nil {
  348. return err
  349. }
  350. } else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
  351. err := validatePtr(field, valueField, containsTag, tag, tagName)
  352. if err != nil {
  353. return err
  354. }
  355. }
  356. return nil
  357. }
  358. func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
  359. if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
  360. if containsregexpTag {
  361. if tagName == "maxItems" {
  362. err := checkMaxItems(field, valueField, tag)
  363. if err != nil {
  364. return err
  365. }
  366. }
  367. if tagName == "minItems" {
  368. err := checkMinItems(field, valueField, tag)
  369. if err != nil {
  370. return err
  371. }
  372. }
  373. }
  374. for m := 0; m < valueField.Len(); m++ {
  375. elementValue := valueField.Index(m)
  376. if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
  377. err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
  378. if err != nil {
  379. return err
  380. }
  381. }
  382. }
  383. }
  384. return nil
  385. }
  386. func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
  387. if elementValue.IsNil() {
  388. return nil
  389. }
  390. if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
  391. if containsregexpTag {
  392. if tagName == "pattern" {
  393. err := checkPattern(field, elementValue.Elem(), tag)
  394. if err != nil {
  395. return err
  396. }
  397. }
  398. if tagName == "maxLength" {
  399. err := checkMaxLength(field, elementValue.Elem(), tag)
  400. if err != nil {
  401. return err
  402. }
  403. }
  404. if tagName == "minLength" {
  405. err := checkMinLength(field, elementValue.Elem(), tag)
  406. if err != nil {
  407. return err
  408. }
  409. }
  410. if tagName == "maximum" {
  411. err := checkMaximum(field, elementValue.Elem(), tag)
  412. if err != nil {
  413. return err
  414. }
  415. }
  416. if tagName == "minimum" {
  417. err := checkMinimum(field, elementValue.Elem(), tag)
  418. if err != nil {
  419. return err
  420. }
  421. }
  422. }
  423. } else {
  424. err := validate(elementValue)
  425. if err != nil {
  426. return err
  427. }
  428. }
  429. return nil
  430. }
  431. func checkRequire(field reflect.StructField, valueField reflect.Value) error {
  432. name, _ := field.Tag.Lookup("json")
  433. strs := strings.Split(name, ",")
  434. name = strs[0]
  435. if !valueField.IsNil() && valueField.IsValid() {
  436. return nil
  437. }
  438. return errors.New(name + " should be setted")
  439. }
  440. func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
  441. if valueField.IsValid() && valueField.String() != "" {
  442. value := valueField.String()
  443. r, _ := regexp.Compile("^" + tag + "$")
  444. if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
  445. return errors.New(value + " is not matched " + tag)
  446. }
  447. }
  448. return nil
  449. }
  450. func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
  451. if valueField.IsValid() && valueField.String() != "" {
  452. maxItems, err := strconv.Atoi(tag)
  453. if err != nil {
  454. return err
  455. }
  456. length := valueField.Len()
  457. if maxItems < length {
  458. errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
  459. return errors.New(errMsg)
  460. }
  461. }
  462. return nil
  463. }
  464. func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
  465. if valueField.IsValid() {
  466. minItems, err := strconv.Atoi(tag)
  467. if err != nil {
  468. return err
  469. }
  470. length := valueField.Len()
  471. if minItems > length {
  472. errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
  473. return errors.New(errMsg)
  474. }
  475. }
  476. return nil
  477. }
  478. func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
  479. if valueField.IsValid() && valueField.String() != "" {
  480. maxLength, err := strconv.Atoi(tag)
  481. if err != nil {
  482. return err
  483. }
  484. length := valueField.Len()
  485. if valueField.Kind().String() == "string" {
  486. length = strings.Count(valueField.String(), "") - 1
  487. }
  488. if maxLength < length {
  489. errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
  490. return errors.New(errMsg)
  491. }
  492. }
  493. return nil
  494. }
  495. func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
  496. if valueField.IsValid() {
  497. minLength, err := strconv.Atoi(tag)
  498. if err != nil {
  499. return err
  500. }
  501. length := valueField.Len()
  502. if valueField.Kind().String() == "string" {
  503. length = strings.Count(valueField.String(), "") - 1
  504. }
  505. if minLength > length {
  506. errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
  507. return errors.New(errMsg)
  508. }
  509. }
  510. return nil
  511. }
  512. func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
  513. if valueField.IsValid() && valueField.String() != "" {
  514. maximum, err := strconv.ParseFloat(tag, 64)
  515. if err != nil {
  516. return err
  517. }
  518. byt, _ := json.Marshal(valueField.Interface())
  519. num, err := strconv.ParseFloat(string(byt), 64)
  520. if err != nil {
  521. return err
  522. }
  523. if maximum < num {
  524. errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
  525. return errors.New(errMsg)
  526. }
  527. }
  528. return nil
  529. }
  530. func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
  531. if valueField.IsValid() && valueField.String() != "" {
  532. minimum, err := strconv.ParseFloat(tag, 64)
  533. if err != nil {
  534. return err
  535. }
  536. byt, _ := json.Marshal(valueField.Interface())
  537. num, err := strconv.ParseFloat(string(byt), 64)
  538. if err != nil {
  539. return err
  540. }
  541. if minimum > num {
  542. errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
  543. return errors.New(errMsg)
  544. }
  545. }
  546. return nil
  547. }