assign_struct.go 7.8 KB

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