github.com/wfusion/gofusion@v1.1.14/common/utils/tag.go (about)

     1  package utils
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  type parseTagOption struct {
     8  	tag           string
     9  	overwrite     bool
    10  	unmarshalType unmarshalType
    11  }
    12  
    13  func ParseTagName(tag string) OptionFunc[parseTagOption] {
    14  	return func(o *parseTagOption) {
    15  		o.tag = tag
    16  	}
    17  }
    18  
    19  func ParseTagOverwrite(overwrite bool) OptionFunc[parseTagOption] {
    20  	return func(o *parseTagOption) {
    21  		o.overwrite = overwrite
    22  	}
    23  }
    24  
    25  func ParseTagUnmarshalType(unmarshalTag unmarshalType) OptionFunc[parseTagOption] {
    26  	return func(o *parseTagOption) {
    27  		o.unmarshalType = unmarshalTag
    28  	}
    29  }
    30  
    31  func ParseTag(data any, opts ...OptionExtender) (err error) {
    32  	opt := ApplyOptions[parseTagOption](opts...)
    33  	stepInKinds := NewSet(reflect.Struct, reflect.Array, reflect.Slice, reflect.Map)
    34  	TraverseValue(data, false, func(field reflect.StructField, value reflect.Value) (end, stepIn bool) {
    35  		if !value.IsValid() || !value.CanSet() || !value.CanAddr() || !value.CanInterface() {
    36  			return
    37  		}
    38  
    39  		vk := value.Kind()
    40  		stepIn = stepInKinds.Contains(vk) ||
    41  			(vk == reflect.Ptr && value.Elem().IsValid() && value.Elem().Kind() == reflect.Struct)
    42  
    43  		defaultString := field.Tag.Get(opt.tag)
    44  		if IsStrBlank(defaultString) || (!opt.overwrite && !IsBlank(value)) {
    45  			return
    46  		}
    47  
    48  		defaultValue := reflect.New(value.Type()).Interface()
    49  		if err = Unmarshal(defaultString, defaultValue, opt.unmarshalType); err != nil {
    50  			end = true
    51  			return
    52  		}
    53  		value.Set(reflect.ValueOf(defaultValue).Elem())
    54  		return
    55  	})
    56  
    57  	return
    58  }