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  }