1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gojsonschema
28
29 import (
30 "bytes"
31 "encoding/json"
32 "errors"
33 "io"
34 "io/ioutil"
35 "net/http"
36 "net/url"
37 "os"
38 "path/filepath"
39 "runtime"
40 "strings"
41
42 "github.com/xeipuuv/gojsonreference"
43 )
44
45 var osFS = osFileSystem(os.Open)
46
47
48 type JSONLoader interface {
49 JsonSource() interface{}
50 LoadJSON() (interface{}, error)
51 JsonReference() (gojsonreference.JsonReference, error)
52 LoaderFactory() JSONLoaderFactory
53 }
54
55
56 type JSONLoaderFactory interface {
57
58 New(source string) JSONLoader
59 }
60
61
62 type DefaultJSONLoaderFactory struct {
63 }
64
65
66 type FileSystemJSONLoaderFactory struct {
67 fs http.FileSystem
68 }
69
70
71 func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
72 return &jsonReferenceLoader{
73 fs: osFS,
74 source: source,
75 }
76 }
77
78
79 func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
80 return &jsonReferenceLoader{
81 fs: f.fs,
82 source: source,
83 }
84 }
85
86
87 type osFileSystem func(string) (*os.File, error)
88
89
90 func (o osFileSystem) Open(name string) (http.File, error) {
91 return o(name)
92 }
93
94
95
96
97 type jsonReferenceLoader struct {
98 fs http.FileSystem
99 source string
100 }
101
102 func (l *jsonReferenceLoader) JsonSource() interface{} {
103 return l.source
104 }
105
106 func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) {
107 return gojsonreference.NewJsonReference(l.JsonSource().(string))
108 }
109
110 func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
111 return &FileSystemJSONLoaderFactory{
112 fs: l.fs,
113 }
114 }
115
116
117 func NewReferenceLoader(source string) JSONLoader {
118 return &jsonReferenceLoader{
119 fs: osFS,
120 source: source,
121 }
122 }
123
124
125 func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) JSONLoader {
126 return &jsonReferenceLoader{
127 fs: fs,
128 source: source,
129 }
130 }
131
132 func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
133
134 var err error
135
136 reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string))
137 if err != nil {
138 return nil, err
139 }
140
141 refToURL := reference
142 refToURL.GetUrl().Fragment = ""
143
144 var document interface{}
145
146 if reference.HasFileScheme {
147
148 filename := strings.TrimPrefix(refToURL.String(), "file://")
149 filename, err = url.QueryUnescape(filename)
150
151 if err != nil {
152 return nil, err
153 }
154
155 if runtime.GOOS == "windows" {
156
157
158 filename = strings.TrimPrefix(filename, "/")
159 filename = filepath.FromSlash(filename)
160 }
161
162 document, err = l.loadFromFile(filename)
163 if err != nil {
164 return nil, err
165 }
166
167 } else {
168
169 document, err = l.loadFromHTTP(refToURL.String())
170 if err != nil {
171 return nil, err
172 }
173
174 }
175
176 return document, nil
177
178 }
179
180 func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
181
182
183
184 if metaSchema := drafts.GetMetaSchema(address); metaSchema != "" {
185 return decodeJSONUsingNumber(strings.NewReader(metaSchema))
186 }
187
188 resp, err := http.Get(address)
189 if err != nil {
190 return nil, err
191 }
192
193
194 if resp.StatusCode != http.StatusOK {
195 return nil, errors.New(formatErrorDescription(Locale.HttpBadStatus(), ErrorDetails{"status": resp.Status}))
196 }
197
198 bodyBuff, err := ioutil.ReadAll(resp.Body)
199 if err != nil {
200 return nil, err
201 }
202
203 return decodeJSONUsingNumber(bytes.NewReader(bodyBuff))
204 }
205
206 func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
207 f, err := l.fs.Open(path)
208 if err != nil {
209 return nil, err
210 }
211 defer f.Close()
212
213 bodyBuff, err := ioutil.ReadAll(f)
214 if err != nil {
215 return nil, err
216 }
217
218 return decodeJSONUsingNumber(bytes.NewReader(bodyBuff))
219
220 }
221
222
223
224 type jsonStringLoader struct {
225 source string
226 }
227
228 func (l *jsonStringLoader) JsonSource() interface{} {
229 return l.source
230 }
231
232 func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) {
233 return gojsonreference.NewJsonReference("#")
234 }
235
236 func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
237 return &DefaultJSONLoaderFactory{}
238 }
239
240
241 func NewStringLoader(source string) JSONLoader {
242 return &jsonStringLoader{source: source}
243 }
244
245 func (l *jsonStringLoader) LoadJSON() (interface{}, error) {
246
247 return decodeJSONUsingNumber(strings.NewReader(l.JsonSource().(string)))
248
249 }
250
251
252
253 type jsonBytesLoader struct {
254 source []byte
255 }
256
257 func (l *jsonBytesLoader) JsonSource() interface{} {
258 return l.source
259 }
260
261 func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) {
262 return gojsonreference.NewJsonReference("#")
263 }
264
265 func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
266 return &DefaultJSONLoaderFactory{}
267 }
268
269
270 func NewBytesLoader(source []byte) JSONLoader {
271 return &jsonBytesLoader{source: source}
272 }
273
274 func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
275 return decodeJSONUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
276 }
277
278
279
280
281 type jsonGoLoader struct {
282 source interface{}
283 }
284
285 func (l *jsonGoLoader) JsonSource() interface{} {
286 return l.source
287 }
288
289 func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) {
290 return gojsonreference.NewJsonReference("#")
291 }
292
293 func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
294 return &DefaultJSONLoaderFactory{}
295 }
296
297
298 func NewGoLoader(source interface{}) JSONLoader {
299 return &jsonGoLoader{source: source}
300 }
301
302 func (l *jsonGoLoader) LoadJSON() (interface{}, error) {
303
304
305
306 jsonBytes, err := json.Marshal(l.JsonSource())
307 if err != nil {
308 return nil, err
309 }
310
311 return decodeJSONUsingNumber(bytes.NewReader(jsonBytes))
312
313 }
314
315 type jsonIOLoader struct {
316 buf *bytes.Buffer
317 }
318
319
320 func NewReaderLoader(source io.Reader) (JSONLoader, io.Reader) {
321 buf := &bytes.Buffer{}
322 return &jsonIOLoader{buf: buf}, io.TeeReader(source, buf)
323 }
324
325
326 func NewWriterLoader(source io.Writer) (JSONLoader, io.Writer) {
327 buf := &bytes.Buffer{}
328 return &jsonIOLoader{buf: buf}, io.MultiWriter(source, buf)
329 }
330
331 func (l *jsonIOLoader) JsonSource() interface{} {
332 return l.buf.String()
333 }
334
335 func (l *jsonIOLoader) LoadJSON() (interface{}, error) {
336 return decodeJSONUsingNumber(l.buf)
337 }
338
339 func (l *jsonIOLoader) JsonReference() (gojsonreference.JsonReference, error) {
340 return gojsonreference.NewJsonReference("#")
341 }
342
343 func (l *jsonIOLoader) LoaderFactory() JSONLoaderFactory {
344 return &DefaultJSONLoaderFactory{}
345 }
346
347
348
349
350
351 type jsonRawLoader struct {
352 source interface{}
353 }
354
355
356 func NewRawLoader(source interface{}) JSONLoader {
357 return &jsonRawLoader{source: source}
358 }
359 func (l *jsonRawLoader) JsonSource() interface{} {
360 return l.source
361 }
362 func (l *jsonRawLoader) LoadJSON() (interface{}, error) {
363 return l.source, nil
364 }
365 func (l *jsonRawLoader) JsonReference() (gojsonreference.JsonReference, error) {
366 return gojsonreference.NewJsonReference("#")
367 }
368 func (l *jsonRawLoader) LoaderFactory() JSONLoaderFactory {
369 return &DefaultJSONLoaderFactory{}
370 }
371
372 func decodeJSONUsingNumber(r io.Reader) (interface{}, error) {
373
374 var document interface{}
375
376 decoder := json.NewDecoder(r)
377 decoder.UseNumber()
378
379 err := decoder.Decode(&document)
380 if err != nil {
381 return nil, err
382 }
383
384 return document, nil
385
386 }
387
View as plain text