github.com/songzhibin97/gkit@v1.2.13/tools/bind/form_mapping.go (about) 1 package bind 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/songzhibin97/gkit/tools/bind/internal/bytesconv" 12 "github.com/songzhibin97/gkit/tools/bind/internal/json" 13 ) 14 15 var errUnknownType = errors.New("unknown type") 16 17 func mapUri(ptr interface{}, m map[string][]string) error { 18 return mapFormByTag(ptr, m, "uri") 19 } 20 21 func mapForm(ptr interface{}, form map[string][]string) error { 22 return mapFormByTag(ptr, form, "form") 23 } 24 25 var emptyField = reflect.StructField{} 26 27 func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error { 28 ptrVal := reflect.ValueOf(ptr) 29 var pointed interface{} 30 // 如果 ptr 是指针 31 if ptrVal.Kind() == reflect.Ptr { 32 // 获取指针内下的值 并且记录一下 当前类型的 interface模式存储在 pointed 位置 33 ptrVal = ptrVal.Elem() 34 pointed = ptrVal.Interface() 35 } 36 if ptrVal.Kind() == reflect.Map && 37 ptrVal.Type().Key().Kind() == reflect.String { 38 // 如果 ptr 是map类型 && 并且 key 是 string 的情况下 39 if pointed != nil { 40 // 如果上面 pointed 不是nil 有值的情况下 ptr = pointed 赋值 41 ptr = pointed 42 } 43 return setFormMap(ptr, form) 44 } 45 46 return mappingByPtr(ptr, formSource(form), tag) 47 } 48 49 // setter tries to set value on a walking by fields of a struct 50 type setter interface { 51 TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error) 52 } 53 54 type formSource map[string][]string 55 56 var _ setter = formSource(nil) 57 58 // TrySet tries to set a value by request's form source (like map[string][]string) 59 func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSetted bool, err error) { 60 return setByForm(value, field, form, tagValue, opt) 61 } 62 63 func mappingByPtr(ptr interface{}, setter setter, tag string) error { 64 // emptyField 空的结构体字段 65 _, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag) 66 return err 67 } 68 69 func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { 70 // 获取 tag, 如果是 "-" 忽略此字段 71 if field.Tag.Get(tag) == "-" { 72 return false, nil 73 } 74 75 vKind := value.Kind() 76 77 // obj kind 如果是指针 78 if vKind == reflect.Ptr { 79 var isNew bool 80 vPtr := value 81 if value.IsNil() { 82 // 如果是空指针 83 // 重新赋值 reflect.New(value.Type().Elem()) 84 isNew = true 85 vPtr = reflect.New(value.Type().Elem()) 86 } 87 isSetted, err := mapping(vPtr.Elem(), field, setter, tag) 88 if err != nil { 89 return false, err 90 } 91 // 如果是新创建的 && 递归成功赋值回去 92 if isNew && isSetted { 93 value.Set(vPtr) 94 } 95 return isSetted, nil 96 } 97 98 // obj kind 不是 struct 或者 不是匿名 99 if vKind != reflect.Struct || !field.Anonymous { 100 // 尝试更新 value 101 ok, err := tryToSetValue(value, field, setter, tag) 102 if err != nil { 103 return false, err 104 } 105 if ok { 106 return true, nil 107 } 108 } 109 110 // obj kind 是 struct 111 if vKind == reflect.Struct { 112 tValue := value.Type() 113 114 // isSetted flag 115 var isSetted bool 116 for i := 0; i < value.NumField(); i++ { 117 118 sf := tValue.Field(i) 119 if sf.PkgPath != "" && !sf.Anonymous { 120 // 未导出内容 121 continue 122 } 123 // 递归子字段 124 ok, err := mapping(value.Field(i), tValue.Field(i), setter, tag) 125 if err != nil { 126 return false, err 127 } 128 isSetted = isSetted || ok 129 } 130 return isSetted, nil 131 } 132 return false, nil 133 } 134 135 type setOptions struct { 136 isDefaultExists bool 137 defaultValue string 138 } 139 140 // tryToSetValue 尝试设置value 141 func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { 142 var tagValue string 143 var setOpt setOptions 144 145 // 获取tag 146 tagValue = field.Tag.Get(tag) 147 // 处理tag,截取第一个有效的 tagValue, opt 将后面剩余的全部返回 148 tagValue, opts := head(tagValue, ",") 149 150 // 如果 tagValue 是空的 就用自己的 字段name 151 if tagValue == "" { 152 tagValue = field.Name 153 } 154 // 如果还是没有的话... 那就是 emptyField 155 if tagValue == "" { 156 return false, nil 157 } 158 159 var opt string 160 // 如果好友其他 tag 161 for len(opts) > 0 { 162 // 再去尝试拿一个 挂到opt上 163 opt, opts = head(opts, ",") 164 // 如果有 default 设置 opt设置为 default模式 165 if k, v := head(opt, "="); k == "default" { 166 setOpt.isDefaultExists = true 167 setOpt.defaultValue = v 168 } 169 } 170 // 尝试设置 171 return setter.TrySet(value, field, tagValue, setOpt) 172 } 173 174 // setByForm 设置 from 模式 175 func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSetted bool, err error) { 176 // 如果tag不存在from或者是没有默认模式 截断返回 177 vs, ok := form[tagValue] 178 if !ok && !opt.isDefaultExists { 179 return false, nil 180 } 181 182 // 判断 value 的类型 处理 183 switch value.Kind() { 184 case reflect.Slice: 185 if !ok { 186 vs = []string{opt.defaultValue} 187 } 188 return true, SetSlice(vs, value, field) 189 case reflect.Array: 190 if !ok { 191 vs = []string{opt.defaultValue} 192 } 193 if len(vs) != value.Len() { 194 return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) 195 } 196 return true, SetArray(vs, value, field) 197 default: 198 var val string 199 if !ok { 200 val = opt.defaultValue 201 } 202 203 if len(vs) > 0 { 204 val = vs[0] 205 } 206 return true, SetWithProperType(val, value, field) 207 } 208 } 209 210 func SetWithProperType(val string, value reflect.Value, field reflect.StructField) error { 211 switch value.Kind() { 212 case reflect.Int: 213 return setIntField(val, 0, value) 214 case reflect.Int8: 215 return setIntField(val, 8, value) 216 case reflect.Int16: 217 return setIntField(val, 16, value) 218 case reflect.Int32: 219 return setIntField(val, 32, value) 220 case reflect.Int64: 221 switch value.Interface().(type) { 222 case time.Duration: 223 return setTimeDuration(val, value) 224 } 225 return setIntField(val, 64, value) 226 case reflect.Uint: 227 return setUintField(val, 0, value) 228 case reflect.Uint8: 229 return setUintField(val, 8, value) 230 case reflect.Uint16: 231 return setUintField(val, 16, value) 232 case reflect.Uint32: 233 return setUintField(val, 32, value) 234 case reflect.Uint64: 235 return setUintField(val, 64, value) 236 case reflect.Bool: 237 return setBoolField(val, value) 238 case reflect.Float32: 239 return setFloatField(val, 32, value) 240 case reflect.Float64: 241 return setFloatField(val, 64, value) 242 case reflect.String: 243 value.SetString(val) 244 case reflect.Struct: 245 switch value.Interface().(type) { 246 case time.Time: 247 return setTimeField(val, field, value) 248 } 249 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) 250 case reflect.Map: 251 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) 252 case reflect.Slice: 253 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) 254 case reflect.Array: 255 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) 256 default: 257 return errUnknownType 258 } 259 return nil 260 } 261 262 func setIntField(val string, bitSize int, field reflect.Value) error { 263 if val == "" { 264 val = "0" 265 } 266 intVal, err := strconv.ParseInt(val, 10, bitSize) 267 if err == nil { 268 field.SetInt(intVal) 269 } 270 return err 271 } 272 273 func setUintField(val string, bitSize int, field reflect.Value) error { 274 if val == "" { 275 val = "0" 276 } 277 uintVal, err := strconv.ParseUint(val, 10, bitSize) 278 if err == nil { 279 field.SetUint(uintVal) 280 } 281 return err 282 } 283 284 func setBoolField(val string, field reflect.Value) error { 285 if val == "" { 286 val = "false" 287 } 288 boolVal, err := strconv.ParseBool(val) 289 if err == nil { 290 field.SetBool(boolVal) 291 } 292 return err 293 } 294 295 func setFloatField(val string, bitSize int, field reflect.Value) error { 296 if val == "" { 297 val = "0.0" 298 } 299 floatVal, err := strconv.ParseFloat(val, bitSize) 300 if err == nil { 301 field.SetFloat(floatVal) 302 } 303 return err 304 } 305 306 func setTimeField(val string, structField reflect.StructField, value reflect.Value) error { 307 timeFormat := structField.Tag.Get("time_format") 308 if timeFormat == "" { 309 timeFormat = time.RFC3339 310 } 311 312 switch tf := strings.ToLower(timeFormat); tf { 313 case "unix", "unixnano": 314 tv, err := strconv.ParseInt(val, 10, 64) 315 if err != nil { 316 return err 317 } 318 319 d := time.Duration(1) 320 if tf == "unixnano" { 321 d = time.Second 322 } 323 324 t := time.Unix(tv/int64(d), tv%int64(d)) 325 value.Set(reflect.ValueOf(t)) 326 return nil 327 } 328 329 if val == "" { 330 value.Set(reflect.ValueOf(time.Time{})) 331 return nil 332 } 333 334 l := time.Local 335 if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC { 336 l = time.UTC 337 } 338 339 if locTag := structField.Tag.Get("time_location"); locTag != "" { 340 loc, err := time.LoadLocation(locTag) 341 if err != nil { 342 return err 343 } 344 l = loc 345 } 346 347 t, err := time.ParseInLocation(timeFormat, val, l) 348 if err != nil { 349 return err 350 } 351 352 value.Set(reflect.ValueOf(t)) 353 return nil 354 } 355 356 func SetArray(vals []string, value reflect.Value, field reflect.StructField) error { 357 for i, s := range vals { 358 err := SetWithProperType(s, value.Index(i), field) 359 if err != nil { 360 return err 361 } 362 } 363 return nil 364 } 365 366 func SetSlice(vals []string, value reflect.Value, field reflect.StructField) error { 367 slice := reflect.MakeSlice(value.Type(), len(vals), len(vals)) 368 err := SetArray(vals, slice, field) 369 if err != nil { 370 return err 371 } 372 value.Set(slice) 373 return nil 374 } 375 376 func setTimeDuration(val string, value reflect.Value) error { 377 d, err := time.ParseDuration(val) 378 if err != nil { 379 return err 380 } 381 value.Set(reflect.ValueOf(d)) 382 return nil 383 } 384 385 // eg: head("t1",",") -> t1,"" 386 // eg: head("t1,t2") -> t1,"t2" 387 // eg: head("t1,t2,t3") -> t1,"t2,t3" 388 func head(str, sep string) (head string, tail string) { 389 idx := strings.Index(str, sep) 390 if idx < 0 { 391 return str, "" 392 } 393 return str[:idx], str[idx+len(sep):] 394 } 395 396 func setFormMap(ptr interface{}, form map[string][]string) error { 397 // el 获取到 key的类型 398 el := reflect.TypeOf(ptr).Elem() 399 400 // 如果是 slice 401 if el.Kind() == reflect.Slice { 402 // 简单断言一下 和 from 类型是否是一致的 403 ptrMap, ok := ptr.(map[string][]string) 404 if !ok { 405 return errors.New("cannot convert to map slices of strings") 406 } 407 // 一致赋值 408 for k, v := range form { 409 ptrMap[k] = v 410 } 411 412 return nil 413 } 414 // 断言 是否是 key:value形式 415 ptrMap, ok := ptr.(map[string]string) 416 if !ok { 417 return errors.New("cannot convert to map of strings") 418 } 419 for k, v := range form { 420 ptrMap[k] = v[len(v)-1] // pick last 421 } 422 423 return nil 424 }