package assign import ( "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger" "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" "reflect" "strings" "time" ) const ( defaultStringSliceSeparator = "::" tagPartSeparator = ";" tagPartKeyValueSeparator = ":" ) const ( tagKey = "assign" tagPartIgnore = "-" tagPartToPackage = "toPackage" tagPartToStruct = "toStruct" tagPartToField = "toField" tagPartTimeLayout = "timeLayout" tagPartJoinWith = "joinWith" tagPartSplitWith = "splitWith" tagPartTrim = "trim" tagPartTrimPrefix = "trimPrefix" tagPartTrimSuffix = "trimSuffix" ) type Tag struct { ToPackage string ToStruct string ToField string TimeLayout string JoinWith string SplitWith string Trim string TrimPrefix string TrimSuffix string } func parseTag(fromElemValue reflect.Value, toElemValue *reflect.Value, onParsedFieldTagFunc OnParsedFieldTagCallback) error { for i := 0; i < fromElemValue.NumField(); i++ { fromField := fromElemValue.Type().Field(i) fromFieldValue := fromElemValue.Field(i) // 无效值 if !fromFieldValue.IsValid() { continue } fromFieldElemValue := reflectutils.PointerValueElem(fromFieldValue) if fromFieldValue.Kind() == reflect.Pointer && fromFieldValue.IsNil() { fromFieldElemValue = reflect.New(fromFieldValue.Type().Elem()).Elem() } tagStr := fromField.Tag.Get(tagKey) // 结构类型的字段上没有添加Tag, 先尝试直接按照字段赋值 if strutils.IsStringEmpty(tagStr) && fromFieldElemValue.Kind() == reflect.Struct && !reflectutils.IsValueTime(fromFieldElemValue) { err := parseTag(fromFieldElemValue, toElemValue, onParsedFieldTagFunc) if err != nil { return err } continue } tag, err := parseFieldTag(fromField, tagStr) if err != nil { return err } if tag == nil { continue } if (strutils.IsStringNotEmpty(tag.ToPackage) && toElemValue.Type().PkgPath() != tag.ToPackage) || (strutils.IsStringNotEmpty(tag.ToStruct) && toElemValue.Type().Name() != tag.ToStruct) { continue } toFieldValue := toElemValue.FieldByName(tag.ToField) // 不存在对应的字段 if !toFieldValue.IsValid() { continue } toFieldElemValue := toFieldValue if toFieldValue.Kind() == reflect.Pointer { if fromFieldValue.Kind() == reflect.Pointer && fromFieldValue.IsNil() { continue } if !toFieldValue.IsValid() { continue } if !toFieldValue.CanSet() { continue } // 空值针,初始化 if toFieldValue.IsNil() { toFieldValue.Set(reflect.New(toFieldValue.Type().Elem())) } toFieldElemValue = toFieldValue.Elem() } err = onParsedFieldTagFunc(fromField.Name, fromFieldElemValue, toFieldElemValue, tag) if err != nil { return err } } return nil } func parseFieldTag(field reflect.StructField, tagStr string) (*Tag, error) { if tagStr == tagPartIgnore { return nil, nil } tag := &Tag{ ToPackage: "", ToStruct: "", ToField: field.Name, TimeLayout: time.DateTime, JoinWith: defaultStringSliceSeparator, SplitWith: defaultStringSliceSeparator, Trim: "", TrimPrefix: "", TrimSuffix: "", } if strutils.IsStringEmpty(tagStr) { return tag, nil } tagParts := strings.Split(tagStr, tagPartSeparator) if tagParts != nil || len(tagParts) != 0 { for _, tagPart := range tagParts { tagPartKeyValue := strings.SplitN(strings.TrimSpace(tagPart), tagPartKeyValueSeparator, 2) if tagPartKeyValue != nil && len(tagPartKeyValue) == 2 && strutils.IsStringNotEmpty(tagPartKeyValue[1]) { tagPartKeyValue[1] = strings.Trim(tagPartKeyValue[1], "'") } if strutils.IsStringEmpty(tagPartKeyValue[0]) { continue } switch tagPartKeyValue[0] { case tagPartToPackage: tag.ToStruct = tagPartKeyValue[1] case tagPartToStruct: tag.ToStruct = tagPartKeyValue[1] case tagPartToField: tag.ToField = tagPartKeyValue[1] case tagPartTimeLayout: tag.TimeLayout = tagPartKeyValue[1] case tagPartJoinWith: if strutils.IsStringEmpty(tagPartKeyValue[1]) { return nil, errors.New(tagPartJoinWith + "没有赋值分隔符") } tag.JoinWith = tagPartKeyValue[1] case tagPartSplitWith: if strutils.IsStringEmpty(tagPartKeyValue[1]) { return nil, errors.New(tagPartSplitWith + "没有赋值分隔符") } tag.SplitWith = tagPartKeyValue[1] case tagPartTrim: tag.Trim = tagPartKeyValue[1] case tagPartTrimPrefix: tag.TrimPrefix = tagPartKeyValue[1] case tagPartTrimSuffix: tag.TrimSuffix = tagPartKeyValue[1] default: err := errors.New(tagKey + "不支持的tag: " + tagPartKeyValue[0]) logger.GetInstance().Error(err) continue } } } return tag, nil }