binding.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package bind
  2. import (
  3. "github.com/gin-gonic/gin/binding"
  4. "reflect"
  5. "strings"
  6. "sync"
  7. )
  8. const (
  9. _ uint8 = iota
  10. json
  11. xml
  12. yaml
  13. form
  14. query
  15. )
  16. var constructor = &bindConstructor{}
  17. type bindConstructor struct {
  18. cache map[string][]uint8
  19. mux sync.Mutex
  20. }
  21. func (e *bindConstructor) GetBindingForGin(d interface{}) []binding.Binding {
  22. bs := e.getBinding(reflect.TypeOf(d).String())
  23. if bs == nil {
  24. //重新构建
  25. bs = e.resolve(d)
  26. }
  27. gbs := make([]binding.Binding, 0)
  28. mp := make(map[uint8]binding.Binding, 0)
  29. for _, b := range bs {
  30. switch b {
  31. case json:
  32. mp[json] = binding.JSON
  33. case xml:
  34. mp[xml] = binding.XML
  35. case yaml:
  36. mp[yaml] = binding.YAML
  37. case form:
  38. mp[form] = binding.Form
  39. case query:
  40. mp[query] = binding.Query
  41. default:
  42. mp[0] = nil
  43. }
  44. }
  45. for e := range mp {
  46. gbs = append(gbs, mp[e])
  47. }
  48. return gbs
  49. }
  50. func (e *bindConstructor) resolve(d interface{}) []uint8 {
  51. bs := make([]uint8, 0)
  52. qType := reflect.TypeOf(d).Elem()
  53. var tag reflect.StructTag
  54. var ok bool
  55. for i := 0; i < qType.NumField(); i++ {
  56. tag = qType.Field(i).Tag
  57. if _, ok = tag.Lookup("json"); ok {
  58. bs = append(bs, json)
  59. }
  60. if _, ok = tag.Lookup("xml"); ok {
  61. bs = append(bs, xml)
  62. }
  63. if _, ok = tag.Lookup("yaml"); ok {
  64. bs = append(bs, yaml)
  65. }
  66. if _, ok = tag.Lookup("form"); ok {
  67. bs = append(bs, form)
  68. }
  69. if _, ok = tag.Lookup("query"); ok {
  70. bs = append(bs, query)
  71. }
  72. if _, ok = tag.Lookup("uri"); ok {
  73. bs = append(bs, 0)
  74. }
  75. if t, ok := tag.Lookup("binding"); ok && strings.Index(t, "dive") > -1 {
  76. qValue := reflect.ValueOf(d)
  77. bs = append(bs, e.resolve(qValue.Field(i))...)
  78. continue
  79. }
  80. if t, ok := tag.Lookup("validate"); ok && strings.Index(t, "dive") > -1 {
  81. qValue := reflect.ValueOf(d)
  82. bs = append(bs, e.resolve(qValue.Field(i))...)
  83. }
  84. }
  85. return bs
  86. }
  87. func (e *bindConstructor) getBinding(name string) []uint8 {
  88. e.mux.Lock()
  89. defer e.mux.Unlock()
  90. return e.cache[name]
  91. }
  92. func (e *bindConstructor) setBinding(name string, bs []uint8) {
  93. e.mux.Lock()
  94. defer e.mux.Unlock()
  95. if e.cache == nil {
  96. e.cache = make(map[string][]uint8)
  97. }
  98. e.cache[name] = bs
  99. }