1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package jsonschema
18
19 import (
20 "fmt"
21 "io/ioutil"
22 "strconv"
23
24 "gopkg.in/yaml.v3"
25 )
26
27
28
29 var schemas map[string]*Schema
30
31
32 func NewBaseSchema() (schema *Schema, err error) {
33 b, err := baseSchemaBytes()
34 if err != nil {
35 return nil, err
36 }
37 var node yaml.Node
38 err = yaml.Unmarshal(b, &node)
39 if err != nil {
40 return nil, err
41 }
42 return NewSchemaFromObject(&node), nil
43 }
44
45
46
47 func NewSchemaFromFile(filename string) (schema *Schema, err error) {
48 file, err := ioutil.ReadFile(filename)
49 if err != nil {
50 return nil, err
51 }
52 var node yaml.Node
53 err = yaml.Unmarshal(file, &node)
54 if err != nil {
55 return nil, err
56 }
57 return NewSchemaFromObject(&node), nil
58 }
59
60
61
62
63 func NewSchemaFromObject(jsonData *yaml.Node) *Schema {
64 switch jsonData.Kind {
65 case yaml.DocumentNode:
66 return NewSchemaFromObject(jsonData.Content[0])
67 case yaml.MappingNode:
68 schema := &Schema{}
69
70 for i := 0; i < len(jsonData.Content); i += 2 {
71 k := jsonData.Content[i].Value
72 v := jsonData.Content[i+1]
73
74 switch k {
75 case "$schema":
76 schema.Schema = schema.stringValue(v)
77 case "id":
78 schema.ID = schema.stringValue(v)
79
80 case "multipleOf":
81 schema.MultipleOf = schema.numberValue(v)
82 case "maximum":
83 schema.Maximum = schema.numberValue(v)
84 case "exclusiveMaximum":
85 schema.ExclusiveMaximum = schema.boolValue(v)
86 case "minimum":
87 schema.Minimum = schema.numberValue(v)
88 case "exclusiveMinimum":
89 schema.ExclusiveMinimum = schema.boolValue(v)
90
91 case "maxLength":
92 schema.MaxLength = schema.intValue(v)
93 case "minLength":
94 schema.MinLength = schema.intValue(v)
95 case "pattern":
96 schema.Pattern = schema.stringValue(v)
97
98 case "additionalItems":
99 schema.AdditionalItems = schema.schemaOrBooleanValue(v)
100 case "items":
101 schema.Items = schema.schemaOrSchemaArrayValue(v)
102 case "maxItems":
103 schema.MaxItems = schema.intValue(v)
104 case "minItems":
105 schema.MinItems = schema.intValue(v)
106 case "uniqueItems":
107 schema.UniqueItems = schema.boolValue(v)
108
109 case "maxProperties":
110 schema.MaxProperties = schema.intValue(v)
111 case "minProperties":
112 schema.MinProperties = schema.intValue(v)
113 case "required":
114 schema.Required = schema.arrayOfStringsValue(v)
115 case "additionalProperties":
116 schema.AdditionalProperties = schema.schemaOrBooleanValue(v)
117 case "properties":
118 schema.Properties = schema.mapOfSchemasValue(v)
119 case "patternProperties":
120 schema.PatternProperties = schema.mapOfSchemasValue(v)
121 case "dependencies":
122 schema.Dependencies = schema.mapOfSchemasOrStringArraysValue(v)
123
124 case "enum":
125 schema.Enumeration = schema.arrayOfEnumValuesValue(v)
126
127 case "type":
128 schema.Type = schema.stringOrStringArrayValue(v)
129 case "allOf":
130 schema.AllOf = schema.arrayOfSchemasValue(v)
131 case "anyOf":
132 schema.AnyOf = schema.arrayOfSchemasValue(v)
133 case "oneOf":
134 schema.OneOf = schema.arrayOfSchemasValue(v)
135 case "not":
136 schema.Not = NewSchemaFromObject(v)
137 case "definitions":
138 schema.Definitions = schema.mapOfSchemasValue(v)
139
140 case "title":
141 schema.Title = schema.stringValue(v)
142 case "description":
143 schema.Description = schema.stringValue(v)
144
145 case "default":
146 schema.Default = v
147
148 case "format":
149 schema.Format = schema.stringValue(v)
150 case "$ref":
151 schema.Ref = schema.stringValue(v)
152 default:
153 fmt.Printf("UNSUPPORTED (%s)\n", k)
154 }
155 }
156
157
158 if schema.ID != nil {
159 if schemas == nil {
160 schemas = make(map[string]*Schema, 0)
161 }
162 schemas[*(schema.ID)] = schema
163 }
164 return schema
165
166 default:
167 fmt.Printf("schemaValue: unexpected node %+v\n", jsonData)
168 return nil
169 }
170
171 return nil
172 }
173
174
175
176
177
178
179
180
181 func (schema *Schema) stringValue(v *yaml.Node) *string {
182 switch v.Kind {
183 case yaml.ScalarNode:
184 return &v.Value
185 default:
186 fmt.Printf("stringValue: unexpected node %+v\n", v)
187 }
188 return nil
189 }
190
191
192 func (schema *Schema) numberValue(v *yaml.Node) *SchemaNumber {
193 number := &SchemaNumber{}
194 switch v.Kind {
195 case yaml.ScalarNode:
196 switch v.Tag {
197 case "!!float":
198 v2, _ := strconv.ParseFloat(v.Value, 64)
199 number.Float = &v2
200 return number
201 case "!!int":
202 v2, _ := strconv.ParseInt(v.Value, 10, 64)
203 number.Integer = &v2
204 return number
205 default:
206 fmt.Printf("stringValue: unexpected node %+v\n", v)
207 }
208 default:
209 fmt.Printf("stringValue: unexpected node %+v\n", v)
210 }
211 return nil
212 }
213
214
215 func (schema *Schema) intValue(v *yaml.Node) *int64 {
216 switch v.Kind {
217 case yaml.ScalarNode:
218 switch v.Tag {
219 case "!!float":
220 v2, _ := strconv.ParseFloat(v.Value, 64)
221 v3 := int64(v2)
222 return &v3
223 case "!!int":
224 v2, _ := strconv.ParseInt(v.Value, 10, 64)
225 return &v2
226 default:
227 fmt.Printf("intValue: unexpected node %+v\n", v)
228 }
229 default:
230 fmt.Printf("intValue: unexpected node %+v\n", v)
231 }
232 return nil
233 }
234
235
236 func (schema *Schema) boolValue(v *yaml.Node) *bool {
237 switch v.Kind {
238 case yaml.ScalarNode:
239 switch v.Tag {
240 case "!!bool":
241 v2, _ := strconv.ParseBool(v.Value)
242 return &v2
243 default:
244 fmt.Printf("boolValue: unexpected node %+v\n", v)
245 }
246 default:
247 fmt.Printf("boolValue: unexpected node %+v\n", v)
248 }
249 return nil
250 }
251
252
253 func (schema *Schema) mapOfSchemasValue(v *yaml.Node) *[]*NamedSchema {
254 switch v.Kind {
255 case yaml.MappingNode:
256 m := make([]*NamedSchema, 0)
257 for i := 0; i < len(v.Content); i += 2 {
258 k2 := v.Content[i].Value
259 v2 := v.Content[i+1]
260 pair := &NamedSchema{Name: k2, Value: NewSchemaFromObject(v2)}
261 m = append(m, pair)
262 }
263 return &m
264 default:
265 fmt.Printf("mapOfSchemasValue: unexpected node %+v\n", v)
266 }
267 return nil
268 }
269
270
271 func (schema *Schema) arrayOfSchemasValue(v *yaml.Node) *[]*Schema {
272 switch v.Kind {
273 case yaml.SequenceNode:
274 m := make([]*Schema, 0)
275 for _, v2 := range v.Content {
276 switch v2.Kind {
277 case yaml.MappingNode:
278 s := NewSchemaFromObject(v2)
279 m = append(m, s)
280 default:
281 fmt.Printf("arrayOfSchemasValue: unexpected node %+v\n", v2)
282 }
283 }
284 return &m
285 case yaml.MappingNode:
286 m := make([]*Schema, 0)
287 s := NewSchemaFromObject(v)
288 m = append(m, s)
289 return &m
290 default:
291 fmt.Printf("arrayOfSchemasValue: unexpected node %+v\n", v)
292 }
293 return nil
294 }
295
296
297 func (schema *Schema) schemaOrSchemaArrayValue(v *yaml.Node) *SchemaOrSchemaArray {
298 switch v.Kind {
299 case yaml.SequenceNode:
300 m := make([]*Schema, 0)
301 for _, v2 := range v.Content {
302 switch v2.Kind {
303 case yaml.MappingNode:
304 s := NewSchemaFromObject(v2)
305 m = append(m, s)
306 default:
307 fmt.Printf("schemaOrSchemaArrayValue: unexpected node %+v\n", v2)
308 }
309 }
310 return &SchemaOrSchemaArray{SchemaArray: &m}
311 case yaml.MappingNode:
312 s := NewSchemaFromObject(v)
313 return &SchemaOrSchemaArray{Schema: s}
314 default:
315 fmt.Printf("schemaOrSchemaArrayValue: unexpected node %+v\n", v)
316 }
317 return nil
318 }
319
320
321 func (schema *Schema) arrayOfStringsValue(v *yaml.Node) *[]string {
322 switch v.Kind {
323 case yaml.ScalarNode:
324 a := []string{v.Value}
325 return &a
326 case yaml.SequenceNode:
327 a := make([]string, 0)
328 for _, v2 := range v.Content {
329 switch v2.Kind {
330 case yaml.ScalarNode:
331 a = append(a, v2.Value)
332 default:
333 fmt.Printf("arrayOfStringsValue: unexpected node %+v\n", v2)
334 }
335 }
336 return &a
337 default:
338 fmt.Printf("arrayOfStringsValue: unexpected node %+v\n", v)
339 }
340 return nil
341 }
342
343
344 func (schema *Schema) stringOrStringArrayValue(v *yaml.Node) *StringOrStringArray {
345 switch v.Kind {
346 case yaml.ScalarNode:
347 s := &StringOrStringArray{}
348 s.String = &v.Value
349 return s
350 case yaml.SequenceNode:
351 a := make([]string, 0)
352 for _, v2 := range v.Content {
353 switch v2.Kind {
354 case yaml.ScalarNode:
355 a = append(a, v2.Value)
356 default:
357 fmt.Printf("arrayOfStringsValue: unexpected node %+v\n", v2)
358 }
359 }
360 s := &StringOrStringArray{}
361 s.StringArray = &a
362 return s
363 default:
364 fmt.Printf("arrayOfStringsValue: unexpected node %+v\n", v)
365 }
366 return nil
367 }
368
369
370 func (schema *Schema) arrayOfEnumValuesValue(v *yaml.Node) *[]SchemaEnumValue {
371 a := make([]SchemaEnumValue, 0)
372 switch v.Kind {
373 case yaml.SequenceNode:
374 for _, v2 := range v.Content {
375 switch v2.Kind {
376 case yaml.ScalarNode:
377 switch v2.Tag {
378 case "!!str":
379 a = append(a, SchemaEnumValue{String: &v2.Value})
380 case "!!bool":
381 v3, _ := strconv.ParseBool(v2.Value)
382 a = append(a, SchemaEnumValue{Bool: &v3})
383 default:
384 fmt.Printf("arrayOfEnumValuesValue: unexpected type %s\n", v2.Tag)
385 }
386 default:
387 fmt.Printf("arrayOfEnumValuesValue: unexpected node %+v\n", v2)
388 }
389 }
390 default:
391 fmt.Printf("arrayOfEnumValuesValue: unexpected node %+v\n", v)
392 }
393 return &a
394 }
395
396
397 func (schema *Schema) mapOfSchemasOrStringArraysValue(v *yaml.Node) *[]*NamedSchemaOrStringArray {
398 m := make([]*NamedSchemaOrStringArray, 0)
399 switch v.Kind {
400 case yaml.MappingNode:
401 for i := 0; i < len(v.Content); i += 2 {
402 k2 := v.Content[i].Value
403 v2 := v.Content[i+1]
404 switch v2.Kind {
405 case yaml.SequenceNode:
406 a := make([]string, 0)
407 for _, v3 := range v2.Content {
408 switch v3.Kind {
409 case yaml.ScalarNode:
410 a = append(a, v3.Value)
411 default:
412 fmt.Printf("mapOfSchemasOrStringArraysValue: unexpected node %+v\n", v3)
413 }
414 }
415 s := &SchemaOrStringArray{}
416 s.StringArray = &a
417 pair := &NamedSchemaOrStringArray{Name: k2, Value: s}
418 m = append(m, pair)
419 default:
420 fmt.Printf("mapOfSchemasOrStringArraysValue: unexpected node %+v\n", v2)
421 }
422 }
423 default:
424 fmt.Printf("mapOfSchemasOrStringArraysValue: unexpected node %+v\n", v)
425 }
426 return &m
427 }
428
429
430 func (schema *Schema) schemaOrBooleanValue(v *yaml.Node) *SchemaOrBoolean {
431 schemaOrBoolean := &SchemaOrBoolean{}
432 switch v.Kind {
433 case yaml.ScalarNode:
434 v2, _ := strconv.ParseBool(v.Value)
435 schemaOrBoolean.Boolean = &v2
436 case yaml.MappingNode:
437 schemaOrBoolean.Schema = NewSchemaFromObject(v)
438 default:
439 fmt.Printf("schemaOrBooleanValue: unexpected node %+v\n", v)
440 }
441 return schemaOrBoolean
442 }
443
View as plain text