...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package gojsonschema
16
17 import (
18 "bytes"
19 "errors"
20
21 "github.com/xeipuuv/gojsonreference"
22 )
23
24
25 type SchemaLoader struct {
26 pool *schemaPool
27 AutoDetect bool
28 Validate bool
29 Draft Draft
30 }
31
32
33 func NewSchemaLoader() *SchemaLoader {
34
35 ps := &SchemaLoader{
36 pool: &schemaPool{
37 schemaPoolDocuments: make(map[string]*schemaPoolDocument),
38 },
39 AutoDetect: true,
40 Validate: false,
41 Draft: Hybrid,
42 }
43 ps.pool.autoDetect = &ps.AutoDetect
44
45 return ps
46 }
47
48 func (sl *SchemaLoader) validateMetaschema(documentNode interface{}) error {
49
50 var (
51 schema string
52 err error
53 )
54 if sl.AutoDetect {
55 schema, _, err = parseSchemaURL(documentNode)
56 if err != nil {
57 return err
58 }
59 }
60
61
62 if schema == "" {
63 if sl.Draft == Hybrid {
64 return nil
65 }
66 schema = drafts.GetSchemaURL(sl.Draft)
67 }
68
69
70 sl.Validate = false
71
72 metaSchema, err := sl.Compile(NewReferenceLoader(schema))
73
74 if err != nil {
75 return err
76 }
77
78 sl.Validate = true
79
80 result := metaSchema.validateDocument(documentNode)
81
82 if !result.Valid() {
83 var res bytes.Buffer
84 for _, err := range result.Errors() {
85 res.WriteString(err.String())
86 res.WriteString("\n")
87 }
88 return errors.New(res.String())
89 }
90
91 return nil
92 }
93
94
95
96 func (sl *SchemaLoader) AddSchemas(loaders ...JSONLoader) error {
97 emptyRef, _ := gojsonreference.NewJsonReference("")
98
99 for _, loader := range loaders {
100 doc, err := loader.LoadJSON()
101
102 if err != nil {
103 return err
104 }
105
106 if sl.Validate {
107 if err := sl.validateMetaschema(doc); err != nil {
108 return err
109 }
110 }
111
112
113
114 if err = sl.pool.parseReferences(doc, emptyRef, false); err != nil {
115 return err
116 }
117 }
118
119 return nil
120 }
121
122
123 func (sl *SchemaLoader) AddSchema(url string, loader JSONLoader) error {
124
125 ref, err := gojsonreference.NewJsonReference(url)
126
127 if err != nil {
128 return err
129 }
130
131 doc, err := loader.LoadJSON()
132
133 if err != nil {
134 return err
135 }
136
137 if sl.Validate {
138 if err := sl.validateMetaschema(doc); err != nil {
139 return err
140 }
141 }
142
143 return sl.pool.parseReferences(doc, ref, true)
144 }
145
146
147 func (sl *SchemaLoader) Compile(rootSchema JSONLoader) (*Schema, error) {
148
149 ref, err := rootSchema.JsonReference()
150
151 if err != nil {
152 return nil, err
153 }
154
155 d := Schema{}
156 d.pool = sl.pool
157 d.pool.jsonLoaderFactory = rootSchema.LoaderFactory()
158 d.documentReference = ref
159 d.referencePool = newSchemaReferencePool()
160
161 var doc interface{}
162 if ref.String() != "" {
163
164 spd, err := d.pool.GetDocument(d.documentReference)
165 if err != nil {
166 return nil, err
167 }
168 doc = spd.Document
169 } else {
170
171 doc, err = rootSchema.LoadJSON()
172 if err != nil {
173 return nil, err
174 }
175
176
177 err = sl.pool.parseReferences(doc, ref, true)
178 if err != nil {
179 return nil, err
180 }
181 }
182
183 if sl.Validate {
184 if err := sl.validateMetaschema(doc); err != nil {
185 return nil, err
186 }
187 }
188
189 draft := sl.Draft
190 if sl.AutoDetect {
191 _, detectedDraft, err := parseSchemaURL(doc)
192 if err != nil {
193 return nil, err
194 }
195 if detectedDraft != nil {
196 draft = *detectedDraft
197 }
198 }
199
200 err = d.parse(doc, draft)
201 if err != nil {
202 return nil, err
203 }
204
205 return &d, nil
206 }
207
View as plain text