|
|
@@ -0,0 +1,226 @@
|
|
|
+package tag
|
|
|
+
|
|
|
+import (
|
|
|
+ "git.sxidc.com/go-framework/baize/infrastructure/logger"
|
|
|
+ "git.sxidc.com/go-tools/utils/strutils"
|
|
|
+ "git.sxidc.com/service-supports/fserr"
|
|
|
+ "reflect"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+func AssignTo[F any, T any](from F) T {
|
|
|
+ var zero T
|
|
|
+
|
|
|
+ assign, err := ParseAssignTag(from)
|
|
|
+ if err != nil {
|
|
|
+ logger.GetInstance().Error(err)
|
|
|
+ return zero
|
|
|
+ }
|
|
|
+
|
|
|
+ retType := reflect.TypeOf(zero)
|
|
|
+ retValue := reflect.New(retType).Elem()
|
|
|
+
|
|
|
+ return retValue.Interface()
|
|
|
+}
|
|
|
+
|
|
|
+const (
|
|
|
+ assignDefaultStringSliceSeparator = "::"
|
|
|
+ assignTagPartSeparator = ";"
|
|
|
+ assignTagPartKeyValueSeparator = ":"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ assignTagKey = "assign"
|
|
|
+ assignIgnore = "-"
|
|
|
+ assignToField = "toField"
|
|
|
+ assignParseTime = "parseTime"
|
|
|
+ assignFormatTime = "formatTime"
|
|
|
+ assignJoinWith = "joinWith"
|
|
|
+ assignSplitWith = "splitWith"
|
|
|
+ assignTrim = "trim"
|
|
|
+ assignTrimLeft = "trimLeft"
|
|
|
+ assignTrimRight = "trimRight"
|
|
|
+)
|
|
|
+
|
|
|
+type Assign struct {
|
|
|
+ AssignElement map[string]any
|
|
|
+}
|
|
|
+
|
|
|
+type AssignElement struct {
|
|
|
+ ToField string
|
|
|
+ ParseTime string
|
|
|
+ FormatTime string
|
|
|
+ JoinWith string
|
|
|
+ SplitWith string
|
|
|
+ Trim string
|
|
|
+ TrimLeft string
|
|
|
+ TrimRight string
|
|
|
+
|
|
|
+ // 原字段的反射结构
|
|
|
+ OriginFieldType reflect.Type
|
|
|
+ OriginFieldValue reflect.Value
|
|
|
+
|
|
|
+ // 值类型的反射结构
|
|
|
+ FieldTypeElem reflect.Type
|
|
|
+ FieldValueElem reflect.Value
|
|
|
+}
|
|
|
+
|
|
|
+func ParseAssignTag(from any) (*Assign, error) {
|
|
|
+ if from == nil {
|
|
|
+ return nil, fserr.New("没有传递结构或结构指针")
|
|
|
+ }
|
|
|
+
|
|
|
+ fromType := reflect.TypeOf(from)
|
|
|
+
|
|
|
+ if fromType.Kind() != reflect.Ptr && fromType.Kind() != reflect.Struct {
|
|
|
+ return nil, fserr.New("参数不是结构或结构指针")
|
|
|
+ }
|
|
|
+
|
|
|
+ if fromType.Kind() == reflect.Ptr && fromType.Elem().Kind() != reflect.Struct {
|
|
|
+ return nil, fserr.New("参数不是结构或结构指针")
|
|
|
+ }
|
|
|
+
|
|
|
+ fromValue := reflect.ValueOf(from)
|
|
|
+ fromElemValue := fromValue
|
|
|
+ if fromType.Kind() == reflect.Ptr {
|
|
|
+ fromElemValue = fromValue.Elem()
|
|
|
+ }
|
|
|
+
|
|
|
+ assign := new(Assign)
|
|
|
+ assign.AssignElement = make(map[string]any)
|
|
|
+
|
|
|
+ for i := 0; i < fromElemValue.NumField(); i++ {
|
|
|
+ field := fromType.Field(i)
|
|
|
+ fieldValue := fromElemValue.Field(i)
|
|
|
+
|
|
|
+ // 零值,不用赋值
|
|
|
+ if !fieldValue.IsValid() {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ element, err := parseSqlMappingElement(field, fieldValue)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if element == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ assign.AssignElement[field.Name] = element
|
|
|
+ }
|
|
|
+
|
|
|
+ return assign, nil
|
|
|
+}
|
|
|
+
|
|
|
+func parseSqlMappingElement(field reflect.StructField, fieldValue reflect.Value) (any, error) {
|
|
|
+ assignTag := field.Tag.Get(assignTagKey)
|
|
|
+ if assignTag == assignIgnore {
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ fieldValueElemType := field.Type
|
|
|
+ if field.Type.Kind() == reflect.Ptr {
|
|
|
+ fieldValueElemType = field.Type.Elem()
|
|
|
+ }
|
|
|
+
|
|
|
+ fieldValueElem := fieldValue
|
|
|
+ if fieldValue.Kind() == reflect.Ptr {
|
|
|
+ fieldValueElem = fieldValue.Elem()
|
|
|
+ }
|
|
|
+
|
|
|
+ if fieldValueElemType.Kind() == reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
|
|
|
+ return ParseAssignTag(fieldValueElem.Interface())
|
|
|
+ }
|
|
|
+
|
|
|
+ element := &AssignElement{
|
|
|
+ ToField: field.Name,
|
|
|
+ ParseTime: time.DateTime,
|
|
|
+ FormatTime: time.DateTime,
|
|
|
+ JoinWith: assignDefaultStringSliceSeparator,
|
|
|
+ SplitWith: assignDefaultStringSliceSeparator,
|
|
|
+ Trim: "",
|
|
|
+ TrimLeft: "",
|
|
|
+ TrimRight: "",
|
|
|
+
|
|
|
+ OriginFieldType: field.Type,
|
|
|
+ OriginFieldValue: fieldValue,
|
|
|
+ FieldTypeElem: fieldValueElemType,
|
|
|
+ FieldValueElem: fieldValueElem,
|
|
|
+ }
|
|
|
+
|
|
|
+ if strutils.IsStringEmpty(assignTag) {
|
|
|
+ return element, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ assignParts := strings.Split(assignTag, 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.TrimSpace(strings.Trim(assignPartKeyValue[1], "'"))
|
|
|
+ }
|
|
|
+
|
|
|
+ switch assignPartKeyValue[0] {
|
|
|
+ case assignToField:
|
|
|
+ element.ToField = assignPartKeyValue[1]
|
|
|
+ case assignParseTime:
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignParseTime + "应该添加在string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.ParseTime = assignPartKeyValue[1]
|
|
|
+ case assignFormatTime:
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
|
|
|
+ return nil, fserr.New(assignFormatTime + "应该添加在time.Time字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.FormatTime = assignPartKeyValue[1]
|
|
|
+ case assignJoinWith:
|
|
|
+ if strutils.IsStringEmpty(assignPartKeyValue[1]) {
|
|
|
+ return nil, fserr.New(assignJoinWith + "没有赋值分隔符")
|
|
|
+ }
|
|
|
+
|
|
|
+ if fieldValueElemType.Kind() != reflect.Slice || fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignJoinWith + "应该添加在[]string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.JoinWith = assignPartKeyValue[1]
|
|
|
+ case assignSplitWith:
|
|
|
+ if strutils.IsStringEmpty(assignPartKeyValue[1]) {
|
|
|
+ return nil, fserr.New(assignSplitWith + "没有赋值分隔符")
|
|
|
+ }
|
|
|
+
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignSplitWith + "应该添加在string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.SplitWith = assignPartKeyValue[1]
|
|
|
+ case assignTrim:
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignTrim + "应该添加在string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.Trim = assignPartKeyValue[1]
|
|
|
+ case assignTrimLeft:
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignTrimLeft + "应该添加在string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.TrimLeft = assignPartKeyValue[1]
|
|
|
+ case assignTrimRight:
|
|
|
+ if fieldValueElemType.Elem().Kind() != reflect.String {
|
|
|
+ return nil, fserr.New(assignTrimRight + "应该添加在string字段上")
|
|
|
+ }
|
|
|
+
|
|
|
+ element.TrimRight = assignPartKeyValue[1]
|
|
|
+ default:
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return element, nil
|
|
|
+}
|