assign_struct.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package tag
  2. import (
  3. "git.sxidc.com/go-framework/baize/infrastructure/logger"
  4. "git.sxidc.com/go-tools/utils/reflectutils"
  5. "git.sxidc.com/go-tools/utils/strutils"
  6. "git.sxidc.com/service-supports/fserr"
  7. "reflect"
  8. "strings"
  9. "time"
  10. )
  11. func AssignTo(from any, to any) error {
  12. if from == nil || to == nil {
  13. return nil
  14. }
  15. fromValue := reflect.ValueOf(from)
  16. retValue := reflect.ValueOf(to)
  17. // 类型校验
  18. if !reflectutils.IsValueStructOrStructPointer(fromValue) {
  19. return fserr.New("参数不是结构或结构指针")
  20. }
  21. if !reflectutils.IsValueStructPointer(retValue) {
  22. return fserr.New("返回类型不是结构指针")
  23. }
  24. fromElemValue := reflectutils.PointerValueElem(fromValue)
  25. retElemValue := reflectutils.PointerValueElem(retValue)
  26. err := assignTo(fromElemValue, &retElemValue)
  27. if err != nil {
  28. return err
  29. }
  30. return nil
  31. }
  32. func assignTo(fromElemValue reflect.Value, retElemValue *reflect.Value) error {
  33. for i := 0; i < fromElemValue.NumField(); i++ {
  34. fromField := fromElemValue.Type().Field(i)
  35. fromFieldValue := fromElemValue.Field(i)
  36. // 无效零值,不进行赋值
  37. if !fromFieldValue.IsValid() || fromFieldValue.IsZero() {
  38. continue
  39. }
  40. tagStr := fromField.Tag.Get(assignTagKey)
  41. // 结构上没有添加Tag, 先尝试直接按照字段赋值结构,如果失败,进一步进入内部尝试
  42. if strutils.IsStringEmpty(tagStr) &&
  43. !reflectutils.IsValueTime(fromFieldValue) &&
  44. !reflectutils.IsValueTimePointer(fromFieldValue) {
  45. if !fromFieldValue.IsValid() || fromFieldValue.IsZero() {
  46. continue
  47. }
  48. err := assignTo(reflectutils.PointerValueElem(fromFieldValue), retElemValue)
  49. if err != nil {
  50. return err
  51. }
  52. }
  53. tag, err := parseAssignTag(fromField, tagStr)
  54. if err != nil {
  55. return err
  56. }
  57. if tag == nil {
  58. continue
  59. }
  60. retFieldValue := retElemValue.FieldByName(tag.ToField)
  61. // 不存在对应的字段
  62. if !retFieldValue.IsValid() {
  63. continue
  64. }
  65. retFieldElemValue := retFieldValue
  66. if retFieldValue.Kind() == reflect.Ptr {
  67. if !retFieldValue.IsValid() {
  68. continue
  69. }
  70. if !retFieldValue.CanSet() {
  71. continue
  72. }
  73. // 空值针,初始化
  74. if retFieldValue.IsNil() {
  75. retFieldValue.Set(reflect.New(retFieldValue.Type().Elem()))
  76. }
  77. retFieldElemValue = retFieldValue.Elem()
  78. }
  79. fromFieldElemValue := reflectutils.PointerValueElem(fromFieldValue)
  80. err = assignField(fromFieldElemValue, retFieldElemValue, tag)
  81. if err != nil {
  82. return err
  83. }
  84. }
  85. return nil
  86. }
  87. func assignField(fromFieldElemValue reflect.Value, retFieldElemValue reflect.Value, tag *assignTag) error {
  88. fromKind := reflectutils.GroupValueKind(fromFieldElemValue)
  89. retKind := reflectutils.GroupValueKind(retFieldElemValue)
  90. var fromAny any
  91. switch fromKind {
  92. case reflect.Struct:
  93. // time.Time类型的结构,接收字段是string类型,使用FormatTime的格式转换
  94. if reflectutils.IsValueTime(fromFieldElemValue) && retKind == reflect.String {
  95. fromString := fromFieldElemValue.Interface().(time.Time).Format(tag.FormatTime)
  96. fromAny = trimFromString(fromString, tag)
  97. break
  98. }
  99. // 不是time.Time类型的结构,接收字段是结构,执行结构到结构字段的赋值
  100. if !reflectutils.IsValueTime(fromFieldElemValue) && retKind == reflect.Struct {
  101. return assignTo(fromFieldElemValue, &retFieldElemValue)
  102. }
  103. // 直接将整个结构进行字段赋值
  104. fromAny = fromFieldElemValue.Interface()
  105. case reflect.Slice:
  106. if reflectutils.IsSliceValueOf(fromFieldElemValue, reflect.String) && retKind == reflect.String {
  107. fromString := strings.Join(fromFieldElemValue.Interface().([]string), tag.JoinWith)
  108. fromAny = trimFromString(fromString, tag)
  109. break
  110. }
  111. fromAny = fromFieldElemValue.Interface()
  112. case reflect.String:
  113. fromString := fromFieldElemValue.String()
  114. if reflectutils.IsValueTime(retFieldElemValue) {
  115. retTimeField, err := time.ParseInLocation(tag.ParseTime, fromString, time.Local)
  116. if err != nil {
  117. return err
  118. }
  119. fromAny = retTimeField
  120. break
  121. }
  122. if reflectutils.IsSliceValueOf(retFieldElemValue, reflect.String) {
  123. fromAny = strings.Split(fromString, tag.SplitWith)
  124. break
  125. }
  126. fromAny = trimFromString(fromString, tag)
  127. default:
  128. fromAny = fromFieldElemValue.Interface()
  129. }
  130. switch retKind {
  131. case reflect.Int64:
  132. return reflectutils.AssignInt64Value(fromAny, retFieldElemValue)
  133. case reflect.Uint64:
  134. return reflectutils.AssignUint64Value(fromAny, retFieldElemValue)
  135. case reflect.Float64:
  136. return reflectutils.AssignFloat64Value(fromAny, retFieldElemValue)
  137. case reflect.Bool:
  138. return reflectutils.AssignBoolValue(fromAny, retFieldElemValue)
  139. case reflect.String:
  140. return reflectutils.AssignStringValue(fromAny, retFieldElemValue)
  141. default:
  142. retFieldElemValue.Set(reflect.ValueOf(fromAny))
  143. return nil
  144. }
  145. }
  146. func trimFromString(fromString string, tag *assignTag) string {
  147. if strutils.IsStringNotEmpty(tag.Trim) {
  148. return strings.Trim(fromString, tag.Trim)
  149. } else {
  150. if strutils.IsStringNotEmpty(tag.TrimPrefix) {
  151. return strings.TrimPrefix(fromString, tag.TrimPrefix)
  152. }
  153. if strutils.IsStringNotEmpty(tag.TrimSuffix) {
  154. return strings.TrimSuffix(fromString, tag.TrimSuffix)
  155. }
  156. }
  157. return fromString
  158. }
  159. const (
  160. assignDefaultStringSliceSeparator = "::"
  161. assignTagPartSeparator = ";"
  162. assignTagPartKeyValueSeparator = ":"
  163. )
  164. const (
  165. assignTagKey = "assign"
  166. assignIgnore = "-"
  167. assignToField = "toField"
  168. assignParseTime = "parseTime"
  169. assignFormatTime = "formatTime"
  170. assignJoinWith = "joinWith"
  171. assignSplitWith = "splitWith"
  172. assignTrim = "trim"
  173. assignTrimPrefix = "trimPrefix"
  174. assignTrimSuffix = "trimSuffix"
  175. )
  176. type assignTag struct {
  177. ToField string
  178. ParseTime string
  179. FormatTime string
  180. JoinWith string
  181. SplitWith string
  182. Trim string
  183. TrimPrefix string
  184. TrimSuffix string
  185. }
  186. func parseAssignTag(field reflect.StructField, tagStr string) (*assignTag, error) {
  187. if tagStr == assignIgnore {
  188. return nil, nil
  189. }
  190. tag := &assignTag{
  191. ToField: field.Name,
  192. ParseTime: time.DateTime,
  193. FormatTime: time.DateTime,
  194. JoinWith: assignDefaultStringSliceSeparator,
  195. SplitWith: assignDefaultStringSliceSeparator,
  196. Trim: "",
  197. TrimPrefix: "",
  198. TrimSuffix: "",
  199. }
  200. if strutils.IsStringEmpty(tagStr) {
  201. return tag, nil
  202. }
  203. assignParts := strings.Split(tagStr, assignTagPartSeparator)
  204. if assignParts != nil || len(assignParts) != 0 {
  205. for _, assignPart := range assignParts {
  206. assignPartKeyValue := strings.SplitN(strings.TrimSpace(assignPart), assignTagPartKeyValueSeparator, 2)
  207. if assignPartKeyValue != nil && len(assignPartKeyValue) == 2 && strutils.IsStringNotEmpty(assignPartKeyValue[1]) {
  208. // 可以支持' ' ',获取到'字符
  209. assignPartKeyValue[1] = strings.TrimSpace(strings.Trim(assignPartKeyValue[1], "'"))
  210. }
  211. switch assignPartKeyValue[0] {
  212. case assignToField:
  213. tag.ToField = assignPartKeyValue[1]
  214. case assignParseTime:
  215. tag.ParseTime = assignPartKeyValue[1]
  216. case assignFormatTime:
  217. tag.FormatTime = assignPartKeyValue[1]
  218. case assignJoinWith:
  219. if strutils.IsStringEmpty(assignPartKeyValue[1]) {
  220. return nil, fserr.New(assignJoinWith + "没有赋值分隔符")
  221. }
  222. tag.JoinWith = assignPartKeyValue[1]
  223. case assignSplitWith:
  224. if strutils.IsStringEmpty(assignPartKeyValue[1]) {
  225. return nil, fserr.New(assignSplitWith + "没有赋值分隔符")
  226. }
  227. tag.SplitWith = assignPartKeyValue[1]
  228. case assignTrim:
  229. tag.Trim = assignPartKeyValue[1]
  230. case assignTrimPrefix:
  231. tag.TrimPrefix = assignPartKeyValue[1]
  232. case assignTrimSuffix:
  233. tag.TrimSuffix = assignPartKeyValue[1]
  234. default:
  235. err := fserr.New(assignTagKey + "不支持的tag: " + assignPartKeyValue[0])
  236. logger.GetInstance().Error(err)
  237. continue
  238. }
  239. }
  240. }
  241. return tag, nil
  242. }