schema_doc.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package yaml_checker
  2. import (
  3. "errors"
  4. "gopkg.in/yaml.v3"
  5. "os"
  6. )
  7. const (
  8. schemaNodeTypeObject = "object"
  9. schemaNodeTypeField = "field"
  10. )
  11. type SchemaDoc struct {
  12. rootSchemas []SchemaNode
  13. }
  14. type SchemaDocYaml struct {
  15. RootSchemas []SchemaYaml `yaml:"schema"`
  16. }
  17. type SchemaYaml struct {
  18. Type string `yaml:"type"`
  19. Name string `yaml:"name"`
  20. Describe string `yaml:"describe"`
  21. Required bool `yaml:"required"`
  22. AsArray bool `yaml:"as_array"`
  23. // object
  24. Fields []SchemaYaml `yaml:"fields"`
  25. // field
  26. FieldType string `yaml:"field_type"`
  27. }
  28. func NewSchemaDoc(schemaFilePath string) (*SchemaDoc, error) {
  29. if isStringEmpty(schemaFilePath) || !pathExists(schemaFilePath) {
  30. return nil, errors.New("schema文件不存在")
  31. }
  32. validatorFileBytes, err := os.ReadFile(schemaFilePath)
  33. if err != nil {
  34. return nil, errors.New("读取schema文件错误: " + err.Error())
  35. }
  36. schemaDocYaml := new(SchemaDocYaml)
  37. err = yaml.Unmarshal(validatorFileBytes, schemaDocYaml)
  38. if err != nil {
  39. return nil, errors.New("schema文件unmarshal错误: " + err.Error())
  40. }
  41. if schemaDocYaml.RootSchemas == nil || len(schemaDocYaml.RootSchemas) == 0 {
  42. return nil, errors.New("schema文件结构错误: 没有根节点")
  43. }
  44. doc := new(SchemaDoc)
  45. for _, rootSchema := range schemaDocYaml.RootSchemas {
  46. rootSchemaNode, err := newSchemaNode(&rootSchema)
  47. if err != nil {
  48. return nil, err
  49. }
  50. doc.rootSchemas = append(doc.rootSchemas, rootSchemaNode)
  51. }
  52. return doc, nil
  53. }
  54. func newSchemaNode(schemaNodeYaml *SchemaYaml) (SchemaNode, error) {
  55. switch schemaNodeYaml.Type {
  56. case schemaNodeTypeObject:
  57. return newObjectSchemaNode(schemaNodeYaml)
  58. case schemaNodeTypeField:
  59. return newFieldSchemaNode(schemaNodeYaml)
  60. default:
  61. return nil, errors.New("不支持的schema节点类型")
  62. }
  63. }
  64. func newObjectSchemaNode(schemaNodeYaml *SchemaYaml) (*ObjectSchemaNode, error) {
  65. if schemaNodeYaml.Type != schemaNodeTypeObject {
  66. return nil, errors.New("schema节点类型错误: 期望类型" + schemaNodeTypeObject + " 实际类型" + schemaNodeYaml.Type)
  67. }
  68. if isStringEmpty(schemaNodeYaml.Name) {
  69. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有name属性")
  70. }
  71. if isStringEmpty(schemaNodeYaml.Describe) {
  72. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有describe属性")
  73. }
  74. if schemaNodeYaml.Fields == nil || len(schemaNodeYaml.Fields) == 0 {
  75. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有fields属性")
  76. }
  77. fieldSchemaNodes := make([]SchemaNode, 0)
  78. for _, field := range schemaNodeYaml.Fields {
  79. fieldSchemaNode, err := newSchemaNode(&field)
  80. if err != nil {
  81. return nil, err
  82. }
  83. fieldSchemaNodes = append(fieldSchemaNodes, fieldSchemaNode)
  84. }
  85. return &ObjectSchemaNode{
  86. BaseNamingSchemaNode: BaseNamingSchemaNode{
  87. Type: schemaNodeYaml.Type,
  88. Name: schemaNodeYaml.Name,
  89. Describe: schemaNodeYaml.Describe,
  90. Required: schemaNodeYaml.Required,
  91. },
  92. AsArray: schemaNodeYaml.AsArray,
  93. Fields: fieldSchemaNodes,
  94. }, nil
  95. }
  96. func newFieldSchemaNode(schemaNodeYaml *SchemaYaml) (*FieldSchemaNode, error) {
  97. if schemaNodeYaml.Type != schemaNodeTypeField {
  98. return nil, errors.New("schema节点类型错误: 期望类型" + schemaNodeTypeField + " 实际类型" + schemaNodeYaml.Type)
  99. }
  100. if isStringEmpty(schemaNodeYaml.Name) {
  101. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有name属性")
  102. }
  103. if isStringEmpty(schemaNodeYaml.Describe) {
  104. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有describe属性")
  105. }
  106. if isStringEmpty(schemaNodeYaml.FieldType) {
  107. return nil, errors.New(schemaNodeTypeObject + "schema类型必须有field_type属性")
  108. }
  109. return &FieldSchemaNode{
  110. BaseNamingSchemaNode: BaseNamingSchemaNode{
  111. Type: schemaNodeYaml.Type,
  112. Name: schemaNodeYaml.Name,
  113. Describe: schemaNodeYaml.Describe,
  114. Required: schemaNodeYaml.Required,
  115. },
  116. AsArray: schemaNodeYaml.AsArray,
  117. FieldType: schemaNodeYaml.FieldType,
  118. }, nil
  119. }
  120. func (schemaDoc *SchemaDoc) ValidateFile(filePath string) error {
  121. if !pathExists(filePath) {
  122. return errors.New("文件不存在: " + filePath)
  123. }
  124. fileBytes, err := os.ReadFile(filePath)
  125. if err != nil {
  126. return errors.New("读取文件错误: " + err.Error())
  127. }
  128. yamlMap := make(map[string]any)
  129. err = yaml.Unmarshal(fileBytes, yamlMap)
  130. if err != nil {
  131. return errors.New("unmarshal文件错误: " + err.Error())
  132. }
  133. return schemaDoc.validate(yamlMap)
  134. }
  135. func (schemaDoc *SchemaDoc) ValidateMap(yamlMap map[string]any) error {
  136. if yamlMap == nil || len(yamlMap) == 0 {
  137. return errors.New("没有yaml的map")
  138. }
  139. return schemaDoc.validate(yamlMap)
  140. }
  141. func (schemaDoc *SchemaDoc) validate(yamlMap map[string]any) error {
  142. for _, rootSchemaNode := range schemaDoc.rootSchemas {
  143. err := rootSchemaNode.Validate(yamlMap)
  144. if err != nil {
  145. return err
  146. }
  147. }
  148. return nil
  149. }