formatter.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package rest
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "gorm.io/gorm"
  7. "reflect"
  8. "strconv"
  9. "sync"
  10. "time"
  11. )
  12. var (
  13. DefaultFormatter = NewFormatter()
  14. DefaultNullDisplay = ""
  15. )
  16. func init() {
  17. DefaultFormatter.Register("string", stringFormat)
  18. DefaultFormatter.Register("integer", integerFormat)
  19. DefaultFormatter.Register("decimal", decimalFormat)
  20. DefaultFormatter.Register("date", dateFormat)
  21. DefaultFormatter.Register("time", timeFormat)
  22. DefaultFormatter.Register("datetime", datetimeFormat)
  23. DefaultFormatter.Register("duration", durationFormat)
  24. DefaultFormatter.Register("dropdown", dropdownFormat)
  25. }
  26. type FormatFunc func(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{}
  27. type Formatter struct {
  28. callbacks sync.Map
  29. }
  30. func (formatter *Formatter) Register(f string, fun FormatFunc) {
  31. formatter.callbacks.Store(f, fun)
  32. }
  33. func (formatter *Formatter) Format(ctx context.Context, format string, value interface{}, model interface{}, scm *Schema) interface{} {
  34. v, ok := formatter.callbacks.Load(format)
  35. if ok {
  36. return v.(FormatFunc)(ctx, value, model, scm)
  37. }
  38. return value
  39. }
  40. func (formatter *Formatter) formatModel(ctx context.Context, val interface{}, schemas []*Schema, stmt *gorm.Statement) interface{} {
  41. values := make(map[string]interface{})
  42. refVal := reflect.Indirect(reflect.ValueOf(val))
  43. for _, field := range schemas {
  44. if stmt.Schema != nil {
  45. f := stmt.Schema.LookUpField(field.Column)
  46. values[field.Column] = formatter.Format(ctx, field.Format, refVal.FieldByName(f.Name).Interface(), val, field)
  47. } else {
  48. values[field.Column] = ""
  49. }
  50. }
  51. return values
  52. }
  53. func (formatter *Formatter) formatModels(ctx context.Context, val interface{}, schemas []*Schema, stmt *gorm.Statement) interface{} {
  54. reflectValue := reflect.Indirect(reflect.ValueOf(val))
  55. if reflectValue.Type().Kind() != reflect.Slice {
  56. return nil
  57. }
  58. length := reflectValue.Len()
  59. values := make([]interface{}, length)
  60. for i := 0; i < length; i++ {
  61. values[i] = formatter.formatModel(ctx, reflectValue.Index(i).Interface(), schemas, stmt)
  62. }
  63. return values
  64. }
  65. func stringFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  66. return fmt.Sprint(value)
  67. }
  68. func integerFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  69. var (
  70. n int
  71. )
  72. switch value.(type) {
  73. case float32, float64:
  74. n = int(reflect.ValueOf(value).Float())
  75. case int, int8, int16, int32, int64:
  76. n = int(reflect.ValueOf(value).Int())
  77. case uint, uint8, uint16, uint32, uint64:
  78. n = int(reflect.ValueOf(value).Uint())
  79. case string:
  80. n, _ = strconv.Atoi(reflect.ValueOf(value).String())
  81. case []byte:
  82. n, _ = strconv.Atoi(string(reflect.ValueOf(value).Bytes()))
  83. }
  84. return n
  85. }
  86. func decimalFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  87. var (
  88. n float64
  89. )
  90. switch value.(type) {
  91. case float32, float64:
  92. n = float64(reflect.ValueOf(value).Float())
  93. case int, int8, int16, int32, int64:
  94. n = float64(reflect.ValueOf(value).Int())
  95. case uint, uint8, uint16, uint32, uint64:
  96. n = float64(reflect.ValueOf(value).Uint())
  97. case string:
  98. n, _ = strconv.ParseFloat(reflect.ValueOf(value).String(), 64)
  99. case []byte:
  100. n, _ = strconv.ParseFloat(string(reflect.ValueOf(value).Bytes()), 64)
  101. }
  102. return n
  103. }
  104. func dateFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  105. if t, ok := value.(time.Time); ok {
  106. return t.Format("2006-01-02")
  107. }
  108. if t, ok := value.(*sql.NullTime); ok {
  109. if t != nil && t.Valid {
  110. return t.Time.Format("2006-01-02")
  111. }
  112. }
  113. if t, ok := value.(int64); ok {
  114. tm := time.Unix(t, 0)
  115. return tm.Format("2006-01-02")
  116. }
  117. return DefaultNullDisplay
  118. }
  119. func timeFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  120. if t, ok := value.(time.Time); ok {
  121. return t.Format("15:04:05")
  122. }
  123. if t, ok := value.(*sql.NullTime); ok {
  124. if t != nil && t.Valid {
  125. return t.Time.Format("15:04:05")
  126. }
  127. }
  128. if t, ok := value.(int64); ok {
  129. tm := time.Unix(t, 0)
  130. return tm.Format("15:04:05")
  131. }
  132. return DefaultNullDisplay
  133. }
  134. func datetimeFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  135. if t, ok := value.(time.Time); ok {
  136. return t.Format("2006-01-02 15:04:05")
  137. }
  138. if t, ok := value.(*sql.NullTime); ok {
  139. if t != nil && t.Valid {
  140. return t.Time.Format("2006-01-02 15:04:05")
  141. }
  142. }
  143. if t, ok := value.(int64); ok {
  144. if t > 0 {
  145. tm := time.Unix(t, 0)
  146. return tm.Format("2006-01-02 15:04:05")
  147. }
  148. }
  149. return DefaultNullDisplay
  150. }
  151. func durationFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  152. var (
  153. hour int
  154. min int
  155. sec int
  156. )
  157. n := integerFormat(ctx, value, model, scm).(int)
  158. hour = n / 3600
  159. min = (n - hour*3600) / 60
  160. sec = n - hour*3600 - min*60
  161. return fmt.Sprintf("%02d:%02d:%02d", hour, min, sec)
  162. }
  163. func dropdownFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  164. attributes := scm.Attribute
  165. if attributes.Values != nil {
  166. for _, v := range attributes.Values {
  167. if v.Value == value {
  168. return v.Label
  169. }
  170. }
  171. }
  172. return value
  173. }
  174. func NewFormatter() *Formatter {
  175. formatter := &Formatter{}
  176. return formatter
  177. }