27
27
package gojsonschema
28
28
29
29
import (
30
- // "encoding/json"
31
30
"errors"
32
31
"reflect"
33
32
"regexp"
@@ -56,10 +55,11 @@ func NewSchema(l JSONLoader) (*Schema, error) {
56
55
d .documentReference = ref
57
56
d .referencePool = newSchemaReferencePool ()
58
57
58
+ var spd * schemaPoolDocument
59
59
var doc interface {}
60
60
if ref .String () != "" {
61
61
// Get document from schema pool
62
- spd , err : = d .pool .GetDocument (d .documentReference )
62
+ spd , err = d .pool .GetDocument (d .documentReference )
63
63
if err != nil {
64
64
return nil , err
65
65
}
@@ -70,8 +70,8 @@ func NewSchema(l JSONLoader) (*Schema, error) {
70
70
if err != nil {
71
71
return nil , err
72
72
}
73
- d .pool .SetStandaloneDocument (doc )
74
73
}
74
+ d .pool .SetStandaloneDocument (doc )
75
75
76
76
err = d .parse (doc )
77
77
if err != nil {
@@ -113,12 +113,48 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
113
113
},
114
114
))
115
115
}
116
+ if currentSchema .parent == nil {
117
+ currentSchema .ref = & d .documentReference
118
+ currentSchema .id = & d .documentReference
119
+ }
120
+
121
+ if currentSchema .id == nil && currentSchema .parent != nil {
122
+ currentSchema .id = currentSchema .parent .id
123
+ }
116
124
117
125
m := documentNode .(map [string ]interface {})
118
126
119
- if currentSchema == d .rootSchema {
120
- currentSchema .ref = & d .documentReference
127
+ // id
128
+ if existsMapKey (m , KEY_ID ) && ! isKind (m [KEY_ID ], reflect .String ) {
129
+ return errors .New (formatErrorDescription (
130
+ Locale .InvalidType (),
131
+ ErrorDetails {
132
+ "expected" : TYPE_STRING ,
133
+ "given" : KEY_ID ,
134
+ },
135
+ ))
121
136
}
137
+ if k , ok := m [KEY_ID ].(string ); ok {
138
+ jsonReference , err := gojsonreference .NewJsonReference (k )
139
+ if err != nil {
140
+ return err
141
+ }
142
+ if currentSchema == d .rootSchema {
143
+ currentSchema .id = & jsonReference
144
+ } else {
145
+ ref , err := currentSchema .parent .id .Inherits (jsonReference )
146
+ if err != nil {
147
+ return err
148
+ }
149
+ currentSchema .id = ref
150
+ }
151
+ }
152
+
153
+ // Add schema to document cache. The same id is passed down to subsequent
154
+ // subschemas, but as only the first and top one is used it will always reference
155
+ // the correct schema. Doing it once here prevents having
156
+ // to do this same step at every corner case.
157
+ d .referencePool .Add (currentSchema .id .String (), currentSchema )
122
158
123
159
// $subSchema
124
160
if existsMapKey (m , KEY_SCHEMA ) {
@@ -159,19 +195,17 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
159
195
if jsonReference .HasFullUrl {
160
196
currentSchema .ref = & jsonReference
161
197
} else {
162
- inheritedReference , err := currentSchema .ref .Inherits (jsonReference )
198
+ inheritedReference , err := currentSchema .id .Inherits (jsonReference )
163
199
if err != nil {
164
200
return err
165
201
}
166
-
167
202
currentSchema .ref = inheritedReference
168
203
}
169
-
170
- if sch , ok := d .referencePool .Get (currentSchema .ref .String () + k ); ok {
204
+ if sch , ok := d .referencePool .Get (currentSchema .ref .String ()); ok {
171
205
currentSchema .refSchema = sch
172
-
173
206
} else {
174
- err := d .parseReference (documentNode , currentSchema , k )
207
+ err := d .parseReference (documentNode , currentSchema )
208
+
175
209
if err != nil {
176
210
return err
177
211
}
@@ -186,11 +220,23 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
186
220
currentSchema .definitions = make (map [string ]* subSchema )
187
221
for dk , dv := range m [KEY_DEFINITIONS ].(map [string ]interface {}) {
188
222
if isKind (dv , reflect .Map ) {
189
- newSchema := & subSchema {property : KEY_DEFINITIONS , parent : currentSchema , ref : currentSchema .ref }
223
+
224
+ ref , err := gojsonreference .NewJsonReference ("#/" + KEY_DEFINITIONS + "/" + dk )
225
+ if err != nil {
226
+ return err
227
+ }
228
+
229
+ newSchemaID , err := currentSchema .id .Inherits (ref )
230
+ if err != nil {
231
+ return err
232
+ }
233
+ newSchema := & subSchema {property : KEY_DEFINITIONS , parent : currentSchema , id : newSchemaID }
190
234
currentSchema .definitions [dk ] = newSchema
191
- err := d .parseSchema (dv , newSchema )
235
+
236
+ err = d .parseSchema (dv , newSchema )
237
+
192
238
if err != nil {
193
- return errors . New ( err . Error ())
239
+ return err
194
240
}
195
241
} else {
196
242
return errors .New (formatErrorDescription (
@@ -214,20 +260,6 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
214
260
215
261
}
216
262
217
- // id
218
- if existsMapKey (m , KEY_ID ) && ! isKind (m [KEY_ID ], reflect .String ) {
219
- return errors .New (formatErrorDescription (
220
- Locale .InvalidType (),
221
- ErrorDetails {
222
- "expected" : TYPE_STRING ,
223
- "given" : KEY_ID ,
224
- },
225
- ))
226
- }
227
- if k , ok := m [KEY_ID ].(string ); ok {
228
- currentSchema .id = & k
229
- }
230
-
231
263
// title
232
264
if existsMapKey (m , KEY_TITLE ) && ! isKind (m [KEY_TITLE ], reflect .String ) {
233
265
return errors .New (formatErrorDescription (
@@ -798,26 +830,32 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
798
830
return nil
799
831
}
800
832
801
- func (d * Schema ) parseReference (documentNode interface {}, currentSchema * subSchema , reference string ) error {
802
- var refdDocumentNode interface {}
833
+ func (d * Schema ) parseReference (documentNode interface {}, currentSchema * subSchema ) error {
834
+ var (
835
+ refdDocumentNode interface {}
836
+ dsp * schemaPoolDocument
837
+ err error
838
+ )
803
839
jsonPointer := currentSchema .ref .GetPointer ()
804
840
standaloneDocument := d .pool .GetStandaloneDocument ()
805
841
806
- if standaloneDocument != nil {
842
+ newSchema := & subSchema { property : KEY_REF , parent : currentSchema , ref : currentSchema . ref }
807
843
808
- var err error
844
+ if currentSchema . ref . HasFragmentOnly {
809
845
refdDocumentNode , _ , err = jsonPointer .Get (standaloneDocument )
810
846
if err != nil {
811
847
return err
812
848
}
813
849
814
850
} else {
815
- dsp , err : = d .pool .GetDocument (* currentSchema .ref )
851
+ dsp , err = d .pool .GetDocument (* currentSchema .ref )
816
852
if err != nil {
817
853
return err
818
854
}
855
+ newSchema .id = currentSchema .ref
819
856
820
857
refdDocumentNode , _ , err = jsonPointer .Get (dsp .Document )
858
+
821
859
if err != nil {
822
860
return err
823
861
}
@@ -833,10 +871,8 @@ func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSche
833
871
834
872
// returns the loaded referenced subSchema for the caller to update its current subSchema
835
873
newSchemaDocument := refdDocumentNode .(map [string ]interface {})
836
- newSchema := & subSchema {property : KEY_REF , parent : currentSchema , ref : currentSchema .ref }
837
- d .referencePool .Add (currentSchema .ref .String ()+ reference , newSchema )
838
874
839
- err : = d .parseSchema (newSchemaDocument , newSchema )
875
+ err = d .parseSchema (newSchemaDocument , newSchema )
840
876
if err != nil {
841
877
return err
842
878
}
0 commit comments