gvalid_check_map.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gvalid
  7. import (
  8. "strings"
  9. "github.com/gogf/gf/util/gconv"
  10. )
  11. // CheckMap validates map and returns the error result. It returns nil if with successful validation.
  12. //
  13. // The parameter <rules> can be type of []string/map[string]string. It supports sequence in error result
  14. // if <rules> is type of []string.
  15. // The optional parameter <messages> specifies the custom error messages for specified keys and rules.
  16. func CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Error {
  17. // If there's no validation rules, it does nothing and returns quickly.
  18. if params == nil || rules == nil {
  19. return nil
  20. }
  21. var (
  22. checkRules = make(map[string]string)
  23. customMsgs = make(CustomMsg)
  24. errorRules = make([]string, 0)
  25. errorMaps = make(ErrorMap)
  26. )
  27. switch v := rules.(type) {
  28. // Sequence tag: []sequence tag
  29. // Sequence has order for error results.
  30. case []string:
  31. for _, tag := range v {
  32. name, rule, msg := parseSequenceTag(tag)
  33. if len(name) == 0 {
  34. continue
  35. }
  36. if len(msg) > 0 {
  37. var (
  38. msgArray = strings.Split(msg, "|")
  39. ruleArray = strings.Split(rule, "|")
  40. )
  41. for k, v := range ruleArray {
  42. // If length of custom messages is lesser than length of rules,
  43. // the rest rules use the default error messages.
  44. if len(msgArray) <= k {
  45. continue
  46. }
  47. if len(msgArray[k]) == 0 {
  48. continue
  49. }
  50. array := strings.Split(v, ":")
  51. if _, ok := customMsgs[name]; !ok {
  52. customMsgs[name] = make(map[string]string)
  53. }
  54. customMsgs[name].(map[string]string)[strings.TrimSpace(array[0])] = strings.TrimSpace(msgArray[k])
  55. }
  56. }
  57. checkRules[name] = rule
  58. errorRules = append(errorRules, name+"@"+rule)
  59. }
  60. // No sequence rules: map[field]rule
  61. case map[string]string:
  62. checkRules = v
  63. }
  64. // If there's no validation rules, it does nothing and returns quickly.
  65. if len(checkRules) == 0 {
  66. return nil
  67. }
  68. data := gconv.Map(params)
  69. if data == nil {
  70. return newErrorStr(
  71. "invalid_params",
  72. "invalid params type: convert to map failed",
  73. )
  74. }
  75. if len(messages) > 0 && len(messages[0]) > 0 {
  76. if len(customMsgs) > 0 {
  77. for k, v := range messages[0] {
  78. customMsgs[k] = v
  79. }
  80. } else {
  81. customMsgs = messages[0]
  82. }
  83. }
  84. var value interface{}
  85. for key, rule := range checkRules {
  86. if len(rule) == 0 {
  87. continue
  88. }
  89. value = nil
  90. if v, ok := data[key]; ok {
  91. value = v
  92. }
  93. // It checks each rule and its value in loop.
  94. if e := doCheck(key, value, rule, customMsgs[key], data); e != nil {
  95. _, item := e.FirstItem()
  96. // ===========================================================
  97. // Only in map and struct validations, if value is nil or empty
  98. // string and has no required* rules, it clears the error message.
  99. // ===========================================================
  100. if gconv.String(value) == "" {
  101. required := false
  102. // rule => error
  103. for k := range item {
  104. // Default required rules.
  105. if _, ok := mustCheckRulesEvenValueEmpty[k]; ok {
  106. required = true
  107. break
  108. }
  109. // Custom rules are also required in default.
  110. if _, ok := customRuleFuncMap[k]; ok {
  111. required = true
  112. break
  113. }
  114. }
  115. if !required {
  116. continue
  117. }
  118. }
  119. if _, ok := errorMaps[key]; !ok {
  120. errorMaps[key] = make(map[string]string)
  121. }
  122. for k, v := range item {
  123. errorMaps[key][k] = v
  124. }
  125. }
  126. }
  127. if len(errorMaps) > 0 {
  128. return newError(errorRules, errorMaps)
  129. }
  130. return nil
  131. }