tag.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package assign
  2. import (
  3. "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger"
  4. "git.sxidc.com/go-tools/utils/reflectutils"
  5. "git.sxidc.com/go-tools/utils/strutils"
  6. "github.com/pkg/errors"
  7. "reflect"
  8. "strings"
  9. "time"
  10. )
  11. const (
  12. defaultStringSliceSeparator = "::"
  13. tagPartSeparator = ";"
  14. tagPartKeyValueSeparator = ":"
  15. )
  16. const (
  17. tagKey = "assign"
  18. tagPartIgnore = "-"
  19. tagPartToPackage = "toPackage"
  20. tagPartToStruct = "toStruct"
  21. tagPartToField = "toField"
  22. tagPartTimeLayout = "timeLayout"
  23. tagPartJoinWith = "joinWith"
  24. tagPartSplitWith = "splitWith"
  25. tagPartTrim = "trim"
  26. tagPartTrimPrefix = "trimPrefix"
  27. tagPartTrimSuffix = "trimSuffix"
  28. )
  29. type Tag struct {
  30. ToPackage string
  31. ToStruct string
  32. ToField string
  33. TimeLayout string
  34. JoinWith string
  35. SplitWith string
  36. Trim string
  37. TrimPrefix string
  38. TrimSuffix string
  39. }
  40. func parseTag(fromElemValue reflect.Value, toElemValue *reflect.Value, onParsedFieldTagFunc OnParsedFieldTagCallback) error {
  41. for i := 0; i < fromElemValue.NumField(); i++ {
  42. fromField := fromElemValue.Type().Field(i)
  43. fromFieldValue := fromElemValue.Field(i)
  44. // 无效值
  45. if !fromFieldValue.IsValid() {
  46. continue
  47. }
  48. if fromFieldValue.Kind() == reflect.Pointer && fromFieldValue.IsNil() {
  49. if !fromFieldValue.CanSet() {
  50. return errors.New("无法设置值,请检查是否传递的是非指针结构变量且字段为nil")
  51. }
  52. fromFieldValue.Set(reflect.New(fromField.Type.Elem()))
  53. }
  54. fromFieldElemValue := reflectutils.PointerValueElem(fromFieldValue)
  55. tagStr := fromField.Tag.Get(tagKey)
  56. // 结构类型的字段上没有添加Tag, 先尝试直接按照字段赋值
  57. if strutils.IsStringEmpty(tagStr) && fromFieldElemValue.Kind() == reflect.Struct &&
  58. !reflectutils.IsValueTime(fromFieldElemValue) {
  59. err := parseTag(fromFieldElemValue, toElemValue, onParsedFieldTagFunc)
  60. if err != nil {
  61. return err
  62. }
  63. continue
  64. }
  65. tag, err := parseFieldTag(fromField, tagStr)
  66. if err != nil {
  67. return err
  68. }
  69. if tag == nil {
  70. continue
  71. }
  72. if (strutils.IsStringNotEmpty(tag.ToPackage) && toElemValue.Type().PkgPath() != tag.ToPackage) ||
  73. (strutils.IsStringNotEmpty(tag.ToStruct) && toElemValue.Type().Name() != tag.ToStruct) {
  74. continue
  75. }
  76. toFieldValue := toElemValue.FieldByName(tag.ToField)
  77. // 不存在对应的字段
  78. if !toFieldValue.IsValid() {
  79. continue
  80. }
  81. toFieldElemValue := toFieldValue
  82. if toFieldValue.Kind() == reflect.Pointer {
  83. if !toFieldValue.IsValid() {
  84. continue
  85. }
  86. if !toFieldValue.CanSet() {
  87. continue
  88. }
  89. // 空值针,初始化
  90. if toFieldValue.IsNil() {
  91. toFieldValue.Set(reflect.New(toFieldValue.Type().Elem()))
  92. }
  93. toFieldElemValue = toFieldValue.Elem()
  94. }
  95. err = onParsedFieldTagFunc(fromField.Name, fromFieldElemValue, toFieldElemValue, tag)
  96. if err != nil {
  97. return err
  98. }
  99. }
  100. return nil
  101. }
  102. func parseFieldTag(field reflect.StructField, tagStr string) (*Tag, error) {
  103. if tagStr == tagPartIgnore {
  104. return nil, nil
  105. }
  106. tag := &Tag{
  107. ToPackage: "",
  108. ToStruct: "",
  109. ToField: field.Name,
  110. TimeLayout: time.DateTime,
  111. JoinWith: defaultStringSliceSeparator,
  112. SplitWith: defaultStringSliceSeparator,
  113. Trim: "",
  114. TrimPrefix: "",
  115. TrimSuffix: "",
  116. }
  117. if strutils.IsStringEmpty(tagStr) {
  118. return tag, nil
  119. }
  120. tagParts := strings.Split(tagStr, tagPartSeparator)
  121. if tagParts != nil || len(tagParts) != 0 {
  122. for _, tagPart := range tagParts {
  123. tagPartKeyValue := strings.SplitN(strings.TrimSpace(tagPart), tagPartKeyValueSeparator, 2)
  124. if tagPartKeyValue != nil && len(tagPartKeyValue) == 2 && strutils.IsStringNotEmpty(tagPartKeyValue[1]) {
  125. tagPartKeyValue[1] = strings.Trim(tagPartKeyValue[1], "'")
  126. }
  127. if strutils.IsStringEmpty(tagPartKeyValue[0]) {
  128. continue
  129. }
  130. switch tagPartKeyValue[0] {
  131. case tagPartToPackage:
  132. tag.ToStruct = tagPartKeyValue[1]
  133. case tagPartToStruct:
  134. tag.ToStruct = tagPartKeyValue[1]
  135. case tagPartToField:
  136. tag.ToField = tagPartKeyValue[1]
  137. case tagPartTimeLayout:
  138. tag.TimeLayout = tagPartKeyValue[1]
  139. case tagPartJoinWith:
  140. if strutils.IsStringEmpty(tagPartKeyValue[1]) {
  141. return nil, errors.New(tagPartJoinWith + "没有赋值分隔符")
  142. }
  143. tag.JoinWith = tagPartKeyValue[1]
  144. case tagPartSplitWith:
  145. if strutils.IsStringEmpty(tagPartKeyValue[1]) {
  146. return nil, errors.New(tagPartSplitWith + "没有赋值分隔符")
  147. }
  148. tag.SplitWith = tagPartKeyValue[1]
  149. case tagPartTrim:
  150. tag.Trim = tagPartKeyValue[1]
  151. case tagPartTrimPrefix:
  152. tag.TrimPrefix = tagPartKeyValue[1]
  153. case tagPartTrimSuffix:
  154. tag.TrimSuffix = tagPartKeyValue[1]
  155. default:
  156. err := errors.New(tagKey + "不支持的tag: " + tagPartKeyValue[0])
  157. logger.GetInstance().Error(err)
  158. continue
  159. }
  160. }
  161. }
  162. return tag, nil
  163. }