assign_struct.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package tag
  2. import (
  3. "git.sxidc.com/go-framework/baize/infrastructure/logger"
  4. "git.sxidc.com/go-tools/utils/strutils"
  5. "git.sxidc.com/service-supports/fserr"
  6. "reflect"
  7. "strings"
  8. "time"
  9. )
  10. func AssignTo[F any, T any](from F) T {
  11. var zero T
  12. assign, err := ParseAssignTag(from)
  13. if err != nil {
  14. logger.GetInstance().Error(err)
  15. return zero
  16. }
  17. retType := reflect.TypeOf(zero)
  18. retValue := reflect.New(retType).Elem()
  19. return retValue.Interface()
  20. }
  21. const (
  22. assignDefaultStringSliceSeparator = "::"
  23. assignTagPartSeparator = ";"
  24. assignTagPartKeyValueSeparator = ":"
  25. )
  26. const (
  27. assignTagKey = "assign"
  28. assignIgnore = "-"
  29. assignToField = "toField"
  30. assignParseTime = "parseTime"
  31. assignFormatTime = "formatTime"
  32. assignJoinWith = "joinWith"
  33. assignSplitWith = "splitWith"
  34. assignTrim = "trim"
  35. assignTrimLeft = "trimLeft"
  36. assignTrimRight = "trimRight"
  37. )
  38. type Assign struct {
  39. AssignElement map[string]any
  40. }
  41. type AssignElement struct {
  42. ToField string
  43. ParseTime string
  44. FormatTime string
  45. JoinWith string
  46. SplitWith string
  47. Trim string
  48. TrimLeft string
  49. TrimRight string
  50. // 原字段的反射结构
  51. OriginFieldType reflect.Type
  52. OriginFieldValue reflect.Value
  53. // 值类型的反射结构
  54. FieldTypeElem reflect.Type
  55. FieldValueElem reflect.Value
  56. }
  57. func ParseAssignTag(from any) (*Assign, error) {
  58. if from == nil {
  59. return nil, fserr.New("没有传递结构或结构指针")
  60. }
  61. fromType := reflect.TypeOf(from)
  62. if fromType.Kind() != reflect.Ptr && fromType.Kind() != reflect.Struct {
  63. return nil, fserr.New("参数不是结构或结构指针")
  64. }
  65. if fromType.Kind() == reflect.Ptr && fromType.Elem().Kind() != reflect.Struct {
  66. return nil, fserr.New("参数不是结构或结构指针")
  67. }
  68. fromValue := reflect.ValueOf(from)
  69. fromElemValue := fromValue
  70. if fromType.Kind() == reflect.Ptr {
  71. fromElemValue = fromValue.Elem()
  72. }
  73. assign := new(Assign)
  74. assign.AssignElement = make(map[string]any)
  75. for i := 0; i < fromElemValue.NumField(); i++ {
  76. field := fromType.Field(i)
  77. fieldValue := fromElemValue.Field(i)
  78. // 零值,不用赋值
  79. if !fieldValue.IsValid() {
  80. continue
  81. }
  82. element, err := parseSqlMappingElement(field, fieldValue)
  83. if err != nil {
  84. return nil, err
  85. }
  86. if element == nil {
  87. continue
  88. }
  89. assign.AssignElement[field.Name] = element
  90. }
  91. return assign, nil
  92. }
  93. func parseSqlMappingElement(field reflect.StructField, fieldValue reflect.Value) (any, error) {
  94. assignTag := field.Tag.Get(assignTagKey)
  95. if assignTag == assignIgnore {
  96. return nil, nil
  97. }
  98. fieldValueElemType := field.Type
  99. if field.Type.Kind() == reflect.Ptr {
  100. fieldValueElemType = field.Type.Elem()
  101. }
  102. fieldValueElem := fieldValue
  103. if fieldValue.Kind() == reflect.Ptr {
  104. fieldValueElem = fieldValue.Elem()
  105. }
  106. if fieldValueElemType.Kind() == reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
  107. return ParseAssignTag(fieldValueElem.Interface())
  108. }
  109. element := &AssignElement{
  110. ToField: field.Name,
  111. ParseTime: time.DateTime,
  112. FormatTime: time.DateTime,
  113. JoinWith: assignDefaultStringSliceSeparator,
  114. SplitWith: assignDefaultStringSliceSeparator,
  115. Trim: "",
  116. TrimLeft: "",
  117. TrimRight: "",
  118. OriginFieldType: field.Type,
  119. OriginFieldValue: fieldValue,
  120. FieldTypeElem: fieldValueElemType,
  121. FieldValueElem: fieldValueElem,
  122. }
  123. if strutils.IsStringEmpty(assignTag) {
  124. return element, nil
  125. }
  126. assignParts := strings.Split(assignTag, assignTagPartSeparator)
  127. if assignParts != nil || len(assignParts) != 0 {
  128. for _, assignPart := range assignParts {
  129. assignPartKeyValue := strings.SplitN(strings.TrimSpace(assignPart), assignTagPartKeyValueSeparator, 2)
  130. if assignPartKeyValue != nil && len(assignPartKeyValue) == 2 && strutils.IsStringNotEmpty(assignPartKeyValue[1]) {
  131. // 可以支持' ' ',获取到'字符
  132. assignPartKeyValue[1] = strings.TrimSpace(strings.Trim(assignPartKeyValue[1], "'"))
  133. }
  134. switch assignPartKeyValue[0] {
  135. case assignToField:
  136. element.ToField = assignPartKeyValue[1]
  137. case assignParseTime:
  138. if fieldValueElemType.Elem().Kind() != reflect.String {
  139. return nil, fserr.New(assignParseTime + "应该添加在string字段上")
  140. }
  141. element.ParseTime = assignPartKeyValue[1]
  142. case assignFormatTime:
  143. if fieldValueElemType.Elem().Kind() != reflect.Struct && fieldValueElemType != reflect.TypeOf(time.Time{}) {
  144. return nil, fserr.New(assignFormatTime + "应该添加在time.Time字段上")
  145. }
  146. element.FormatTime = assignPartKeyValue[1]
  147. case assignJoinWith:
  148. if strutils.IsStringEmpty(assignPartKeyValue[1]) {
  149. return nil, fserr.New(assignJoinWith + "没有赋值分隔符")
  150. }
  151. if fieldValueElemType.Kind() != reflect.Slice || fieldValueElemType.Elem().Kind() != reflect.String {
  152. return nil, fserr.New(assignJoinWith + "应该添加在[]string字段上")
  153. }
  154. element.JoinWith = assignPartKeyValue[1]
  155. case assignSplitWith:
  156. if strutils.IsStringEmpty(assignPartKeyValue[1]) {
  157. return nil, fserr.New(assignSplitWith + "没有赋值分隔符")
  158. }
  159. if fieldValueElemType.Elem().Kind() != reflect.String {
  160. return nil, fserr.New(assignSplitWith + "应该添加在string字段上")
  161. }
  162. element.SplitWith = assignPartKeyValue[1]
  163. case assignTrim:
  164. if fieldValueElemType.Elem().Kind() != reflect.String {
  165. return nil, fserr.New(assignTrim + "应该添加在string字段上")
  166. }
  167. element.Trim = assignPartKeyValue[1]
  168. case assignTrimLeft:
  169. if fieldValueElemType.Elem().Kind() != reflect.String {
  170. return nil, fserr.New(assignTrimLeft + "应该添加在string字段上")
  171. }
  172. element.TrimLeft = assignPartKeyValue[1]
  173. case assignTrimRight:
  174. if fieldValueElemType.Elem().Kind() != reflect.String {
  175. return nil, fserr.New(assignTrimRight + "应该添加在string字段上")
  176. }
  177. element.TrimRight = assignPartKeyValue[1]
  178. default:
  179. continue
  180. }
  181. }
  182. }
  183. return element, nil
  184. }