subSchema.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // author xeipuuv
  15. // author-github https://github.com/xeipuuv
  16. // author-mail [email protected]
  17. //
  18. // repository-name gojsonschema
  19. // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language.
  20. //
  21. // description Defines the structure of a sub-subSchema.
  22. // A sub-subSchema can contain other sub-schemas.
  23. //
  24. // created 27-02-2013
  25. package gojsonschema
  26. import (
  27. "errors"
  28. "regexp"
  29. "strings"
  30. "github.com/xeipuuv/gojsonreference"
  31. )
  32. const (
  33. KEY_SCHEMA = "$subSchema"
  34. KEY_ID = "$id"
  35. KEY_REF = "$ref"
  36. KEY_TITLE = "title"
  37. KEY_DESCRIPTION = "description"
  38. KEY_TYPE = "type"
  39. KEY_ITEMS = "items"
  40. KEY_ADDITIONAL_ITEMS = "additionalItems"
  41. KEY_PROPERTIES = "properties"
  42. KEY_PATTERN_PROPERTIES = "patternProperties"
  43. KEY_ADDITIONAL_PROPERTIES = "additionalProperties"
  44. KEY_DEFINITIONS = "definitions"
  45. KEY_MULTIPLE_OF = "multipleOf"
  46. KEY_MINIMUM = "minimum"
  47. KEY_MAXIMUM = "maximum"
  48. KEY_EXCLUSIVE_MINIMUM = "exclusiveMinimum"
  49. KEY_EXCLUSIVE_MAXIMUM = "exclusiveMaximum"
  50. KEY_MIN_LENGTH = "minLength"
  51. KEY_MAX_LENGTH = "maxLength"
  52. KEY_PATTERN = "pattern"
  53. KEY_FORMAT = "format"
  54. KEY_MIN_PROPERTIES = "minProperties"
  55. KEY_MAX_PROPERTIES = "maxProperties"
  56. KEY_DEPENDENCIES = "dependencies"
  57. KEY_REQUIRED = "required"
  58. KEY_MIN_ITEMS = "minItems"
  59. KEY_MAX_ITEMS = "maxItems"
  60. KEY_UNIQUE_ITEMS = "uniqueItems"
  61. KEY_ENUM = "enum"
  62. KEY_ONE_OF = "oneOf"
  63. KEY_ANY_OF = "anyOf"
  64. KEY_ALL_OF = "allOf"
  65. KEY_NOT = "not"
  66. )
  67. type subSchema struct {
  68. // basic subSchema meta properties
  69. id *string
  70. title *string
  71. description *string
  72. property string
  73. // Types associated with the subSchema
  74. types jsonSchemaType
  75. // Reference url
  76. ref *gojsonreference.JsonReference
  77. // Schema referenced
  78. refSchema *subSchema
  79. // Json reference
  80. subSchema *gojsonreference.JsonReference
  81. // hierarchy
  82. parent *subSchema
  83. definitions map[string]*subSchema
  84. definitionsChildren []*subSchema
  85. itemsChildren []*subSchema
  86. itemsChildrenIsSingleSchema bool
  87. propertiesChildren []*subSchema
  88. // validation : number / integer
  89. multipleOf *float64
  90. maximum *float64
  91. exclusiveMaximum bool
  92. minimum *float64
  93. exclusiveMinimum bool
  94. // validation : string
  95. minLength *int
  96. maxLength *int
  97. pattern *regexp.Regexp
  98. format string
  99. // validation : object
  100. minProperties *int
  101. maxProperties *int
  102. required []string
  103. dependencies map[string]interface{}
  104. additionalProperties interface{}
  105. patternProperties map[string]*subSchema
  106. // validation : array
  107. minItems *int
  108. maxItems *int
  109. uniqueItems bool
  110. additionalItems interface{}
  111. // validation : all
  112. enum []string
  113. // validation : subSchema
  114. oneOf []*subSchema
  115. anyOf []*subSchema
  116. allOf []*subSchema
  117. not *subSchema
  118. }
  119. func (s *subSchema) AddEnum(i interface{}) error {
  120. is, err := marshalToJsonString(i)
  121. if err != nil {
  122. return err
  123. }
  124. if isStringInSlice(s.enum, *is) {
  125. return errors.New(formatErrorDescription(
  126. Locale.KeyItemsMustBeUnique(),
  127. ErrorDetails{"key": KEY_ENUM},
  128. ))
  129. }
  130. s.enum = append(s.enum, *is)
  131. return nil
  132. }
  133. func (s *subSchema) ContainsEnum(i interface{}) (bool, error) {
  134. is, err := marshalToJsonString(i)
  135. if err != nil {
  136. return false, err
  137. }
  138. return isStringInSlice(s.enum, *is), nil
  139. }
  140. func (s *subSchema) AddOneOf(subSchema *subSchema) {
  141. s.oneOf = append(s.oneOf, subSchema)
  142. }
  143. func (s *subSchema) AddAllOf(subSchema *subSchema) {
  144. s.allOf = append(s.allOf, subSchema)
  145. }
  146. func (s *subSchema) AddAnyOf(subSchema *subSchema) {
  147. s.anyOf = append(s.anyOf, subSchema)
  148. }
  149. func (s *subSchema) SetNot(subSchema *subSchema) {
  150. s.not = subSchema
  151. }
  152. func (s *subSchema) AddRequired(value string) error {
  153. if isStringInSlice(s.required, value) {
  154. return errors.New(formatErrorDescription(
  155. Locale.KeyItemsMustBeUnique(),
  156. ErrorDetails{"key": KEY_REQUIRED},
  157. ))
  158. }
  159. s.required = append(s.required, value)
  160. return nil
  161. }
  162. func (s *subSchema) AddDefinitionChild(child *subSchema) {
  163. s.definitionsChildren = append(s.definitionsChildren, child)
  164. }
  165. func (s *subSchema) AddItemsChild(child *subSchema) {
  166. s.itemsChildren = append(s.itemsChildren, child)
  167. }
  168. func (s *subSchema) AddPropertiesChild(child *subSchema) {
  169. s.propertiesChildren = append(s.propertiesChildren, child)
  170. }
  171. func (s *subSchema) PatternPropertiesString() string {
  172. if s.patternProperties == nil || len(s.patternProperties) == 0 {
  173. return STRING_UNDEFINED // should never happen
  174. }
  175. patternPropertiesKeySlice := []string{}
  176. for pk, _ := range s.patternProperties {
  177. patternPropertiesKeySlice = append(patternPropertiesKeySlice, `"`+pk+`"`)
  178. }
  179. if len(patternPropertiesKeySlice) == 1 {
  180. return patternPropertiesKeySlice[0]
  181. }
  182. return "[" + strings.Join(patternPropertiesKeySlice, ",") + "]"
  183. }