|
|
@@ -1,306 +0,0 @@
|
|
|
-package tag
|
|
|
-
|
|
|
-import (
|
|
|
- "git.sxidc.com/go-framework/baize/infrastructure/logger"
|
|
|
- "git.sxidc.com/go-tools/utils/reflectutils"
|
|
|
- "git.sxidc.com/go-tools/utils/strutils"
|
|
|
- "git.sxidc.com/service-supports/fserr"
|
|
|
- "reflect"
|
|
|
- "strings"
|
|
|
- "time"
|
|
|
-)
|
|
|
-
|
|
|
-type OnAssignParsedFieldTagFunc func(fromFieldName string, fromFieldElemValue reflect.Value, toFieldElementValue reflect.Value, assignTag *AssignTag) error
|
|
|
-
|
|
|
-func UseAssignTag(from any, to any, onParsedFieldTagFunc OnAssignParsedFieldTagFunc) error {
|
|
|
- if from == nil || to == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- fromValue := reflect.ValueOf(from)
|
|
|
- toValue := reflect.ValueOf(to)
|
|
|
-
|
|
|
- // 类型校验
|
|
|
- if !reflectutils.IsValueStructOrStructPointer(fromValue) {
|
|
|
- return fserr.New("参数不是结构或结构指针")
|
|
|
- }
|
|
|
-
|
|
|
- if !reflectutils.IsValueStructPointer(toValue) {
|
|
|
- return fserr.New("返回类型不是结构指针")
|
|
|
- }
|
|
|
-
|
|
|
- fromElemValue := reflectutils.PointerValueElem(fromValue)
|
|
|
- toElemValue := reflectutils.PointerValueElem(toValue)
|
|
|
-
|
|
|
- for i := 0; i < toElemValue.NumField(); i++ {
|
|
|
- toField := toElemValue.Field(i)
|
|
|
- if !toField.IsValid() {
|
|
|
- return fserr.New("被赋值的结构存在无效字段")
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化空值指针
|
|
|
- if toField.Kind() == reflect.Ptr && toField.IsNil() {
|
|
|
- toField.Set(reflect.New(toField.Type().Elem()))
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- err := parseStructAssignTag(fromElemValue, &toElemValue, onParsedFieldTagFunc)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func DefaultOnAssignParsedFieldTagFunc(fromFieldElemValue reflect.Value, toFieldElemValue reflect.Value, assignTag *AssignTag) error {
|
|
|
- fromKind := reflectutils.GroupValueKind(fromFieldElemValue)
|
|
|
- toKind := reflectutils.GroupValueKind(toFieldElemValue)
|
|
|
-
|
|
|
- var fromAny any
|
|
|
- switch fromKind {
|
|
|
- case reflect.Struct:
|
|
|
- // time.Time类型的结构,接收字段是string类型,使用FormatTime的格式转换
|
|
|
- if reflectutils.IsValueTime(fromFieldElemValue) && toKind == reflect.String {
|
|
|
- fromString := fromFieldElemValue.Interface().(time.Time).Format(assignTag.FormatTime)
|
|
|
- fromAny = assignTrimFromString(fromString, assignTag)
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- // 不是time.Time类型的结构,接收字段是结构,执行结构到结构字段的赋值
|
|
|
- if !reflectutils.IsValueTime(fromFieldElemValue) && toKind == reflect.Struct {
|
|
|
- return parseStructAssignTag(fromFieldElemValue, &toFieldElemValue, func(fromFieldName string, fromFieldElemValue reflect.Value, toFieldElementValue reflect.Value, tag *AssignTag) error {
|
|
|
- return DefaultOnAssignParsedFieldTagFunc(fromFieldElemValue, toFieldElementValue, assignTag)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 直接将整个结构进行字段赋值
|
|
|
- fromAny = fromFieldElemValue.Interface()
|
|
|
- case reflect.Slice:
|
|
|
- if reflectutils.IsSliceValueOf(fromFieldElemValue, reflect.String) && toKind == reflect.String {
|
|
|
- fromString := strings.Join(fromFieldElemValue.Interface().([]string), assignTag.JoinWith)
|
|
|
- fromAny = assignTrimFromString(fromString, assignTag)
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- fromAny = fromFieldElemValue.Interface()
|
|
|
- case reflect.String:
|
|
|
- fromString := fromFieldElemValue.String()
|
|
|
-
|
|
|
- if reflectutils.IsValueTime(toFieldElemValue) {
|
|
|
- toTimeField, err := time.ParseInLocation(assignTag.ParseTime, fromString, time.Local)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- fromAny = toTimeField
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- if reflectutils.IsSliceValueOf(toFieldElemValue, reflect.String) {
|
|
|
- fromAny = strings.Split(fromString, assignTag.SplitWith)
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- fromAny = assignTrimFromString(fromString, assignTag)
|
|
|
- default:
|
|
|
- fromAny = fromFieldElemValue.Interface()
|
|
|
- }
|
|
|
-
|
|
|
- switch toKind {
|
|
|
- case reflect.Int64:
|
|
|
- return reflectutils.AssignInt64Value(fromAny, toFieldElemValue)
|
|
|
- case reflect.Uint64:
|
|
|
- return reflectutils.AssignUint64Value(fromAny, toFieldElemValue)
|
|
|
- case reflect.Float64:
|
|
|
- return reflectutils.AssignFloat64Value(fromAny, toFieldElemValue)
|
|
|
- case reflect.Bool:
|
|
|
- return reflectutils.AssignBoolValue(fromAny, toFieldElemValue)
|
|
|
- case reflect.String:
|
|
|
- return reflectutils.AssignStringValue(fromAny, toFieldElemValue)
|
|
|
- default:
|
|
|
- toFieldElemValue.Set(reflect.ValueOf(fromAny))
|
|
|
- return nil
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func assignTrimFromString(fromString string, assignTag *AssignTag) string {
|
|
|
- if strutils.IsStringNotEmpty(assignTag.Trim) {
|
|
|
- return strings.Trim(fromString, assignTag.Trim)
|
|
|
- } else {
|
|
|
- if strutils.IsStringNotEmpty(assignTag.TrimPrefix) {
|
|
|
- return strings.TrimPrefix(fromString, assignTag.TrimPrefix)
|
|
|
- }
|
|
|
-
|
|
|
- if strutils.IsStringNotEmpty(assignTag.TrimSuffix) {
|
|
|
- return strings.TrimSuffix(fromString, assignTag.TrimSuffix)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return fromString
|
|
|
-}
|
|
|
-
|
|
|
-func parseStructAssignTag(fromElemValue reflect.Value, toElemValue *reflect.Value, onParsedFieldTagFunc OnAssignParsedFieldTagFunc) error {
|
|
|
- for i := 0; i < fromElemValue.NumField(); i++ {
|
|
|
- fromField := fromElemValue.Type().Field(i)
|
|
|
- fromFieldValue := fromElemValue.Field(i)
|
|
|
-
|
|
|
- // 无效值
|
|
|
- if !fromFieldValue.IsValid() {
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- if fromFieldValue.Kind() == reflect.Pointer && fromFieldValue.IsNil() {
|
|
|
- fromFieldValue.Set(reflect.New(fromField.Type.Elem()))
|
|
|
- }
|
|
|
-
|
|
|
- fromFieldElemValue := reflectutils.PointerValueElem(fromFieldValue)
|
|
|
-
|
|
|
- tagStr := fromField.Tag.Get(assignTagKey)
|
|
|
-
|
|
|
- // 结构类型的字段上没有添加Tag, 先尝试直接按照字段赋值
|
|
|
- if strutils.IsStringEmpty(tagStr) && fromFieldElemValue.Kind() == reflect.Struct &&
|
|
|
- !reflectutils.IsValueTime(fromFieldElemValue) {
|
|
|
- err := parseStructAssignTag(fromFieldElemValue, toElemValue, onParsedFieldTagFunc)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- assignTag, err := parseAssignTag(fromField, tagStr)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- if assignTag == nil {
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- toFieldValue := toElemValue.FieldByName(assignTag.ToField)
|
|
|
-
|
|
|
- // 不存在对应的字段
|
|
|
- if !toFieldValue.IsValid() {
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- toFieldElemValue := toFieldValue
|
|
|
- if toFieldValue.Kind() == reflect.Pointer {
|
|
|
- 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, assignTag)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-const (
|
|
|
- assignDefaultStringSliceSeparator = "::"
|
|
|
- assignTagPartSeparator = ";"
|
|
|
- assignTagPartKeyValueSeparator = ":"
|
|
|
-)
|
|
|
-
|
|
|
-const (
|
|
|
- assignTagKey = "assign"
|
|
|
- assignIgnore = "-"
|
|
|
- assignToField = "toField"
|
|
|
- assignParseTime = "parseTime"
|
|
|
- assignFormatTime = "formatTime"
|
|
|
- assignJoinWith = "joinWith"
|
|
|
- assignSplitWith = "splitWith"
|
|
|
- assignTrim = "trim"
|
|
|
- assignTrimPrefix = "trimPrefix"
|
|
|
- assignTrimSuffix = "trimSuffix"
|
|
|
-)
|
|
|
-
|
|
|
-type AssignTag struct {
|
|
|
- ToField string
|
|
|
- ParseTime string
|
|
|
- FormatTime string
|
|
|
- JoinWith string
|
|
|
- SplitWith string
|
|
|
- Trim string
|
|
|
- TrimPrefix string
|
|
|
- TrimSuffix string
|
|
|
-}
|
|
|
-
|
|
|
-func parseAssignTag(field reflect.StructField, tagStr string) (*AssignTag, error) {
|
|
|
- if tagStr == assignIgnore {
|
|
|
- return nil, nil
|
|
|
- }
|
|
|
-
|
|
|
- assignTag := &AssignTag{
|
|
|
- ToField: field.Name,
|
|
|
- ParseTime: time.DateTime,
|
|
|
- FormatTime: time.DateTime,
|
|
|
- JoinWith: assignDefaultStringSliceSeparator,
|
|
|
- SplitWith: assignDefaultStringSliceSeparator,
|
|
|
- Trim: "",
|
|
|
- TrimPrefix: "",
|
|
|
- TrimSuffix: "",
|
|
|
- }
|
|
|
-
|
|
|
- if strutils.IsStringEmpty(tagStr) {
|
|
|
- return assignTag, nil
|
|
|
- }
|
|
|
-
|
|
|
- assignParts := strings.Split(tagStr, assignTagPartSeparator)
|
|
|
- if assignParts != nil || len(assignParts) != 0 {
|
|
|
- for _, assignPart := range assignParts {
|
|
|
- assignPartKeyValue := strings.SplitN(strings.TrimSpace(assignPart), assignTagPartKeyValueSeparator, 2)
|
|
|
- if assignPartKeyValue != nil && len(assignPartKeyValue) == 2 && strutils.IsStringNotEmpty(assignPartKeyValue[1]) {
|
|
|
- assignPartKeyValue[1] = strings.Trim(assignPartKeyValue[1], "'")
|
|
|
- }
|
|
|
-
|
|
|
- switch assignPartKeyValue[0] {
|
|
|
- case assignToField:
|
|
|
- assignTag.ToField = assignPartKeyValue[1]
|
|
|
- case assignParseTime:
|
|
|
- assignTag.ParseTime = assignPartKeyValue[1]
|
|
|
- case assignFormatTime:
|
|
|
- assignTag.FormatTime = assignPartKeyValue[1]
|
|
|
- case assignJoinWith:
|
|
|
- if strutils.IsStringEmpty(assignPartKeyValue[1]) {
|
|
|
- return nil, fserr.New(assignJoinWith + "没有赋值分隔符")
|
|
|
- }
|
|
|
-
|
|
|
- assignTag.JoinWith = assignPartKeyValue[1]
|
|
|
- case assignSplitWith:
|
|
|
- if strutils.IsStringEmpty(assignPartKeyValue[1]) {
|
|
|
- return nil, fserr.New(assignSplitWith + "没有赋值分隔符")
|
|
|
- }
|
|
|
-
|
|
|
- assignTag.SplitWith = assignPartKeyValue[1]
|
|
|
- case assignTrim:
|
|
|
- assignTag.Trim = assignPartKeyValue[1]
|
|
|
- case assignTrimPrefix:
|
|
|
- assignTag.TrimPrefix = assignPartKeyValue[1]
|
|
|
- case assignTrimSuffix:
|
|
|
- assignTag.TrimSuffix = assignPartKeyValue[1]
|
|
|
- default:
|
|
|
- err := fserr.New(assignTagKey + "不支持的tag: " + assignPartKeyValue[0])
|
|
|
- logger.GetInstance().Error(err)
|
|
|
- continue
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return assignTag, nil
|
|
|
-}
|