2727package gojsonschema
2828
2929import (
30- // "encoding/json"
3130 "errors"
3231 "reflect"
3332 "regexp"
@@ -56,10 +55,11 @@ func NewSchema(l JSONLoader) (*Schema, error) {
5655 d .documentReference = ref
5756 d .referencePool = newSchemaReferencePool ()
5857
58+ var spd * schemaPoolDocument
5959 var doc interface {}
6060 if ref .String () != "" {
6161 // Get document from schema pool
62- spd , err : = d .pool .GetDocument (d .documentReference )
62+ spd , err = d .pool .GetDocument (d .documentReference )
6363 if err != nil {
6464 return nil , err
6565 }
@@ -70,8 +70,8 @@ func NewSchema(l JSONLoader) (*Schema, error) {
7070 if err != nil {
7171 return nil , err
7272 }
73- d .pool .SetStandaloneDocument (doc )
7473 }
74+ d .pool .SetStandaloneDocument (doc )
7575
7676 err = d .parse (doc )
7777 if err != nil {
@@ -113,12 +113,48 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
113113 },
114114 ))
115115 }
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+ }
116124
117125 m := documentNode .(map [string ]interface {})
118126
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+ ))
121136 }
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 )
122158
123159 // $subSchema
124160 if existsMapKey (m , KEY_SCHEMA ) {
@@ -159,19 +195,17 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
159195 if jsonReference .HasFullUrl {
160196 currentSchema .ref = & jsonReference
161197 } else {
162- inheritedReference , err := currentSchema .ref .Inherits (jsonReference )
198+ inheritedReference , err := currentSchema .id .Inherits (jsonReference )
163199 if err != nil {
164200 return err
165201 }
166-
167202 currentSchema .ref = inheritedReference
168203 }
169-
170- if sch , ok := d .referencePool .Get (currentSchema .ref .String () + k ); ok {
204+ if sch , ok := d .referencePool .Get (currentSchema .ref .String ()); ok {
171205 currentSchema .refSchema = sch
172-
173206 } else {
174- err := d .parseReference (documentNode , currentSchema , k )
207+ err := d .parseReference (documentNode , currentSchema )
208+
175209 if err != nil {
176210 return err
177211 }
@@ -186,11 +220,23 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
186220 currentSchema .definitions = make (map [string ]* subSchema )
187221 for dk , dv := range m [KEY_DEFINITIONS ].(map [string ]interface {}) {
188222 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 }
190234 currentSchema .definitions [dk ] = newSchema
191- err := d .parseSchema (dv , newSchema )
235+
236+ err = d .parseSchema (dv , newSchema )
237+
192238 if err != nil {
193- return errors . New ( err . Error ())
239+ return err
194240 }
195241 } else {
196242 return errors .New (formatErrorDescription (
@@ -214,20 +260,6 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
214260
215261 }
216262
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-
231263 // title
232264 if existsMapKey (m , KEY_TITLE ) && ! isKind (m [KEY_TITLE ], reflect .String ) {
233265 return errors .New (formatErrorDescription (
@@ -798,26 +830,32 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
798830 return nil
799831}
800832
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+ )
803839 jsonPointer := currentSchema .ref .GetPointer ()
804840 standaloneDocument := d .pool .GetStandaloneDocument ()
805841
806- if standaloneDocument != nil {
842+ newSchema := & subSchema { property : KEY_REF , parent : currentSchema , ref : currentSchema . ref }
807843
808- var err error
844+ if currentSchema . ref . HasFragmentOnly {
809845 refdDocumentNode , _ , err = jsonPointer .Get (standaloneDocument )
810846 if err != nil {
811847 return err
812848 }
813849
814850 } else {
815- dsp , err : = d .pool .GetDocument (* currentSchema .ref )
851+ dsp , err = d .pool .GetDocument (* currentSchema .ref )
816852 if err != nil {
817853 return err
818854 }
855+ newSchema .id = currentSchema .ref
819856
820857 refdDocumentNode , _ , err = jsonPointer .Get (dsp .Document )
858+
821859 if err != nil {
822860 return err
823861 }
@@ -833,10 +871,8 @@ func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSche
833871
834872 // returns the loaded referenced subSchema for the caller to update its current subSchema
835873 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 )
838874
839- err : = d .parseSchema (newSchemaDocument , newSchema )
875+ err = d .parseSchema (newSchemaDocument , newSchema )
840876 if err != nil {
841877 return err
842878 }
0 commit comments