github.com/gogf/gf@v1.16.9/util/gvalid/gvalid_validator_check_map.go (about) 1 // Copyright GoFrame Author(https://goframe.org). 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 7 package gvalid 8 9 import ( 10 "github.com/gogf/gf/errors/gcode" 11 "github.com/gogf/gf/util/gconv" 12 "strings" 13 ) 14 15 // CheckMap validates map and returns the error result. It returns nil if with successful validation. 16 // The parameter `params` should be type of map. 17 func (v *Validator) CheckMap(params interface{}) Error { 18 return v.doCheckMap(params) 19 } 20 21 func (v *Validator) doCheckMap(params interface{}) Error { 22 // If there's no validation rules, it does nothing and returns quickly. 23 if params == nil || v.rules == nil { 24 return nil 25 } 26 var ( 27 checkRules = make([]fieldRule, 0) 28 customMessage = make(CustomMsg) // map[RuleKey]ErrorMsg. 29 errorMaps = make(map[string]map[string]string) 30 ) 31 switch assertValue := v.rules.(type) { 32 // Sequence tag: []sequence tag 33 // Sequence has order for error results. 34 case []string: 35 for _, tag := range assertValue { 36 name, rule, msg := parseSequenceTag(tag) 37 if len(name) == 0 { 38 continue 39 } 40 if len(msg) > 0 { 41 var ( 42 msgArray = strings.Split(msg, "|") 43 ruleArray = strings.Split(rule, "|") 44 ) 45 for k, ruleItem := range ruleArray { 46 // If length of custom messages is lesser than length of rules, 47 // the rest rules use the default error messages. 48 if len(msgArray) <= k { 49 continue 50 } 51 if len(msgArray[k]) == 0 { 52 continue 53 } 54 array := strings.Split(ruleItem, ":") 55 if _, ok := customMessage[name]; !ok { 56 customMessage[name] = make(map[string]string) 57 } 58 customMessage[name].(map[string]string)[strings.TrimSpace(array[0])] = strings.TrimSpace(msgArray[k]) 59 } 60 } 61 checkRules = append(checkRules, fieldRule{ 62 Name: name, 63 Rule: rule, 64 }) 65 } 66 67 // No sequence rules: map[field]rule 68 case map[string]string: 69 for name, rule := range assertValue { 70 checkRules = append(checkRules, fieldRule{ 71 Name: name, 72 Rule: rule, 73 }) 74 } 75 } 76 // If there's no validation rules, it does nothing and returns quickly. 77 if len(checkRules) == 0 { 78 return nil 79 } 80 data := gconv.Map(params) 81 if data == nil { 82 return newErrorStr( 83 internalParamsErrRuleName, 84 "invalid params type: convert to map failed", 85 ) 86 } 87 if msg, ok := v.messages.(CustomMsg); ok && len(msg) > 0 { 88 if len(customMessage) > 0 { 89 for k, v := range msg { 90 customMessage[k] = v 91 } 92 } else { 93 customMessage = msg 94 } 95 } 96 var ( 97 value interface{} 98 ) 99 for _, checkRuleItem := range checkRules { 100 if len(checkRuleItem.Rule) == 0 { 101 continue 102 } 103 value = nil 104 if valueItem, ok := data[checkRuleItem.Name]; ok { 105 value = valueItem 106 } 107 // It checks each rule and its value in loop. 108 if validatedError := v.doCheckValue(doCheckValueInput{ 109 Name: checkRuleItem.Name, 110 Value: value, 111 Rule: checkRuleItem.Rule, 112 Messages: customMessage[checkRuleItem.Name], 113 DataRaw: params, 114 DataMap: data, 115 }); validatedError != nil { 116 _, errorItem := validatedError.FirstItem() 117 // =========================================================== 118 // Only in map and struct validations, if value is nil or empty 119 // string and has no required* rules, it clears the error message. 120 // =========================================================== 121 if gconv.String(value) == "" { 122 required := false 123 // rule => error 124 for ruleKey := range errorItem { 125 // Default required rules. 126 if _, ok := mustCheckRulesEvenValueEmpty[ruleKey]; ok { 127 required = true 128 break 129 } 130 // Custom rules are also required in default. 131 if f := v.getRuleFunc(ruleKey); f != nil { 132 required = true 133 break 134 } 135 } 136 if !required { 137 continue 138 } 139 } 140 if _, ok := errorMaps[checkRuleItem.Name]; !ok { 141 errorMaps[checkRuleItem.Name] = make(map[string]string) 142 } 143 for ruleKey, errorItemMsgMap := range errorItem { 144 errorMaps[checkRuleItem.Name][ruleKey] = errorItemMsgMap 145 } 146 if v.bail { 147 break 148 } 149 } 150 } 151 if len(errorMaps) > 0 { 152 return newError(gcode.CodeValidationFailed, checkRules, errorMaps) 153 } 154 return nil 155 }