schema.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package main
  2. import (
  3. "reflect"
  4. "sort"
  5. "strings"
  6. )
  7. type Schema struct {
  8. Name string
  9. Package string
  10. Fields []Field
  11. Doc string
  12. }
  13. type Alias struct {
  14. Name string
  15. Package string
  16. Underlying TypeRef
  17. }
  18. type Field struct {
  19. JSONName string
  20. GoName string
  21. Type TypeRef
  22. Optional bool
  23. Skip bool
  24. Validate []ValidateRule
  25. Doc string
  26. }
  27. type TypeRef struct {
  28. Kind TypeKind
  29. Name string
  30. Element *TypeRef
  31. Key *TypeRef
  32. Value *TypeRef
  33. Inner *TypeRef
  34. }
  35. type TypeKind string
  36. const (
  37. KindString TypeKind = "string"
  38. KindNumber TypeKind = "number"
  39. KindInt TypeKind = "int"
  40. KindBool TypeKind = "boolean"
  41. KindArray TypeKind = "array"
  42. KindMap TypeKind = "map"
  43. KindObject TypeKind = "object"
  44. KindRef TypeKind = "ref"
  45. KindUnknown TypeKind = "unknown"
  46. KindAny TypeKind = "any"
  47. KindRaw TypeKind = "raw"
  48. )
  49. type ValidateRule struct {
  50. Name string
  51. Param string
  52. }
  53. func parseStructTag(raw string) (json string, validate string, gormHasDash bool) {
  54. tag := reflect.StructTag(strings.Trim(raw, "`"))
  55. json = tag.Get("json")
  56. validate = tag.Get("validate")
  57. if g := tag.Get("gorm"); g != "" {
  58. for _, part := range strings.Split(g, ";") {
  59. if strings.TrimSpace(part) == "-" {
  60. gormHasDash = true
  61. }
  62. }
  63. }
  64. return
  65. }
  66. func parseJSONTag(tag string) (name string, omit bool, omitempty bool) {
  67. if tag == "" {
  68. return "", false, false
  69. }
  70. parts := strings.Split(tag, ",")
  71. name = parts[0]
  72. if name == "-" {
  73. return "", true, false
  74. }
  75. for _, p := range parts[1:] {
  76. if p == "omitempty" {
  77. omitempty = true
  78. }
  79. }
  80. return
  81. }
  82. func parseValidateTag(tag string) []ValidateRule {
  83. if tag == "" {
  84. return nil
  85. }
  86. var rules []ValidateRule
  87. for _, part := range strings.Split(tag, ",") {
  88. part = strings.TrimSpace(part)
  89. if part == "" {
  90. continue
  91. }
  92. eq := strings.IndexByte(part, '=')
  93. if eq < 0 {
  94. rules = append(rules, ValidateRule{Name: part})
  95. continue
  96. }
  97. rules = append(rules, ValidateRule{Name: part[:eq], Param: part[eq+1:]})
  98. }
  99. return rules
  100. }
  101. func (s Schema) HasValidationOn(field string) bool {
  102. for _, f := range s.Fields {
  103. if f.JSONName == field {
  104. return len(f.Validate) > 0
  105. }
  106. }
  107. return false
  108. }
  109. func sortSchemas(in []Schema) []Schema {
  110. out := make([]Schema, len(in))
  111. copy(out, in)
  112. sort.Slice(out, func(i, j int) bool {
  113. return out[i].Name < out[j].Name
  114. })
  115. return out
  116. }
  117. func sortAliases(in []Alias) []Alias {
  118. out := make([]Alias, len(in))
  119. copy(out, in)
  120. sort.Slice(out, func(i, j int) bool {
  121. return out[i].Name < out[j].Name
  122. })
  123. return out
  124. }
  125. func flattenEmbedded(schemas []Schema) []Schema {
  126. byName := make(map[string]Schema, len(schemas))
  127. for _, s := range schemas {
  128. byName[s.Name] = s
  129. }
  130. out := make([]Schema, 0, len(schemas))
  131. for _, s := range schemas {
  132. var resolved []Field
  133. seen := make(map[string]bool, len(s.Fields))
  134. for _, f := range s.Fields {
  135. if f.Type.Kind == KindRef && f.Type.Name != "nullable" {
  136. if embedded, ok := byName[f.Type.Name]; ok && f.GoName == f.Type.Name {
  137. for _, ef := range embedded.Fields {
  138. if seen[ef.JSONName] {
  139. continue
  140. }
  141. seen[ef.JSONName] = true
  142. resolved = append(resolved, ef)
  143. }
  144. continue
  145. }
  146. }
  147. if seen[f.JSONName] {
  148. continue
  149. }
  150. seen[f.JSONName] = true
  151. resolved = append(resolved, f)
  152. }
  153. s.Fields = resolved
  154. out = append(out, s)
  155. }
  156. return out
  157. }