github.com/profzone/eden-framework@v1.0.10/pkg/courier/transport_http/transform/utils.go (about) 1 package transform 2 3 import ( 4 "encoding" 5 "encoding/json" 6 "reflect" 7 "strconv" 8 "strings" 9 10 "github.com/sirupsen/logrus" 11 12 "github.com/profzone/eden-framework/pkg/env" 13 "github.com/profzone/eden-framework/pkg/reflectx" 14 "github.com/profzone/eden-framework/pkg/strings" 15 ) 16 17 type TagFlags map[string]bool 18 19 func GetTagValueAndFlags(tagString string) (v string, tagFlags TagFlags) { 20 valueAndFlags := strings.Split(tagString, ",") 21 v = valueAndFlags[0] 22 tagFlags = TagFlags{} 23 if len(valueAndFlags) > 1 { 24 for _, flag := range valueAndFlags[1:] { 25 tagFlags[flag] = true 26 } 27 } 28 return 29 } 30 31 func GetStructFieldDisplayName(field *reflect.StructField) string { 32 if jsonName, exists, _ := GetTagJSON(field); exists && jsonName != "" { 33 return jsonName 34 } 35 return field.Name 36 } 37 38 func GetParameterDisplayName(field *reflect.StructField) (string, TagFlags) { 39 if fieldName, exists, flags := GetTagName(field); exists && fieldName != "" { 40 return fieldName, flags 41 } 42 if jsonName, exists, flags := GetTagJSON(field); exists && jsonName != "" { 43 if !env.IsOnline() { 44 //logrus.Warnf("%s `%s`, deprecated `json` tag for naming parameter, please use `name` tag instead", field.Name, field.Tag) 45 } 46 return jsonName, flags 47 } 48 return field.Name, TagFlags{} 49 } 50 51 func GetTagJSON(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) { 52 name, exists = field.Tag.Lookup("json") 53 if exists { 54 name, tagFlags = GetTagValueAndFlags(name) 55 } 56 return 57 } 58 59 func GetTagName(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) { 60 name, exists = field.Tag.Lookup("name") 61 if exists { 62 name, tagFlags = GetTagValueAndFlags(name) 63 } 64 return 65 } 66 67 func GetTagStyle(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) { 68 name, exists = field.Tag.Lookup("style") 69 if exists { 70 name, tagFlags = GetTagValueAndFlags(name) 71 } 72 return 73 } 74 75 func GetTagFmt(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) { 76 name, exists = field.Tag.Lookup("fmt") 77 if exists { 78 name, tagFlags = GetTagValueAndFlags(name) 79 } 80 return 81 } 82 83 func GetTagDefault(field *reflect.StructField) (string, bool) { 84 return field.Tag.Lookup("default") 85 } 86 87 func GetTagValidate(field *reflect.StructField) (string, bool) { 88 return field.Tag.Lookup("validate") 89 } 90 91 func GetTagErrMsg(field *reflect.StructField) (string, bool) { 92 return field.Tag.Lookup("errMsg") 93 } 94 95 func GetTagIn(field *reflect.StructField) (tagIn string, hasIn bool, tagInFlags map[string]bool) { 96 tagIn, hasIn = field.Tag.Lookup("in") 97 if hasIn { 98 tagIn, tagInFlags = GetTagValueAndFlags(tagIn) 99 } 100 return 101 } 102 103 func MustStructValue(functionName string, rv reflect.Value) { 104 if rv.Kind() != reflect.Struct { 105 logrus.Panicf("%s args must a struct value, but got %+v %+v", functionName, rv.Type(), rv.Interface()) 106 } 107 } 108 109 func Stringify(v interface{}) ([]byte, error) { 110 if marshaler, ok := v.(json.Marshaler); ok { 111 return Unquote(marshaler.MarshalJSON()) 112 } 113 if textMarshaler, ok := v.(encoding.TextMarshaler); ok { 114 return textMarshaler.MarshalText() 115 } 116 s, err := str.ConvertToStr(v) 117 if err != nil { 118 return nil, err 119 } 120 return []byte(s), nil 121 } 122 123 func Unquote(data []byte, err error) ([]byte, error) { 124 if err != nil { 125 return nil, err 126 } 127 if len(data) > 2 { 128 if string(data[0]) == `"` && string(data[len(data)-1]) == `"` { 129 return data[1 : len(data)-1], nil 130 } 131 } 132 return data, err 133 } 134 135 func ResolveCommaSplitValues(tpe reflect.Type, ss ...string) (values []string) { 136 tpe = reflectx.IndirectType(tpe) 137 if tpe.Kind() == reflect.Slice || tpe.Kind() == reflect.Array { 138 itemTpe := reflectx.IndirectType(tpe.Elem()) 139 if !(itemTpe.Kind() == reflect.Struct || itemTpe.Kind() == reflect.Map) { 140 for _, s := range ss { 141 values = append(values, strings.Split(s, ",")...) 142 } 143 return 144 } 145 } 146 return ss 147 } 148 149 func LocateJSONPath(data []byte, offset int64) string { 150 i := 0 151 arrayPaths := map[string]bool{} 152 arrayIdxSet := map[string]int{} 153 pathWalker := &PathWalker{} 154 155 markObjectKey := func() { 156 jsonKey, l := nextString(data[i:]) 157 i += l 158 159 if i < int(offset) && len(jsonKey) > 0 { 160 key, _ := strconv.Unquote(string(jsonKey)) 161 pathWalker.Enter(key) 162 } 163 } 164 165 markArrayIdx := func(path string) { 166 if arrayPaths[path] { 167 arrayIdxSet[path]++ 168 } else { 169 arrayPaths[path] = true 170 } 171 pathWalker.Enter(arrayIdxSet[path]) 172 } 173 174 for i < int(offset) { 175 i += nextToken(data[i:]) 176 char := data[i] 177 178 switch char { 179 case '"': 180 _, l := nextString(data[i:]) 181 i += l 182 case '[', '{': 183 i++ 184 185 if char == '[' { 186 markArrayIdx(pathWalker.String()) 187 } else { 188 markObjectKey() 189 } 190 case '}', ']', ',': 191 i++ 192 pathWalker.Exit() 193 194 if char == ',' { 195 path := pathWalker.String() 196 197 if _, ok := arrayPaths[path]; ok { 198 markArrayIdx(path) 199 } else { 200 markObjectKey() 201 } 202 } 203 default: 204 i++ 205 } 206 } 207 208 return pathWalker.String() 209 } 210 211 func nextToken(data []byte) int { 212 for i, c := range data { 213 switch c { 214 case ' ', '\n', '\r', '\t': 215 continue 216 default: 217 return i 218 } 219 } 220 return -1 221 } 222 223 func nextString(data []byte) (finalData []byte, l int) { 224 quoteStartAt := -1 225 for i, c := range data { 226 switch c { 227 case '"': 228 if i > 0 && string(data[i-1]) == "\\" { 229 continue 230 } 231 if quoteStartAt >= 0 { 232 return data[quoteStartAt : i+1], i + 1 233 } else { 234 quoteStartAt = i 235 } 236 default: 237 continue 238 } 239 } 240 return nil, 0 241 }