@@ -82,20 +82,30 @@ public class SchemaLoader {
82
82
COMBINED_SUBSCHEMA_PROVIDERS .put ("oneOf" , CombinedSchema ::oneOf );
83
83
}
84
84
85
+ /**
86
+ * Loads a JSON schema to a schema validator using a {@link HttpClients#createDefault() default
87
+ * HTTP client}.
88
+ *
89
+ * @param schemaJson
90
+ * the JSON representation of the schema.
91
+ * @return the schema validator object
92
+ */
85
93
public static Schema load (final JSONObject schemaJson ) {
86
94
return load (schemaJson , HttpClients .createDefault ());
87
95
}
88
96
89
97
/**
90
98
* Creates Schema instance from its JSON representation.
99
+ *
100
+ * @param schemaJson
101
+ * the JSON representation of the schema.
102
+ * @param httpClient
103
+ * the HTTP client to be used for resolving remote JSON references.
91
104
*/
92
105
public static Schema load (final JSONObject schemaJson , final HttpClient httpClient ) {
93
106
String schemaId = schemaJson .optString ("id" );
94
- SchemaLoader loader = new SchemaLoader (schemaId , schemaJson , schemaJson , null , httpClient );
95
- Schema .Builder <?> schemaBuilder = loader .load ();
96
- Schema schema = schemaBuilder .build ();
97
- loader .rootReferences .forEach (ref -> ref .build ().setReferredSchema (schema ));
98
- return schema ;
107
+ return new SchemaLoader (schemaId , schemaJson , schemaJson , new HashMap <>(), httpClient )
108
+ .load ().build ();
99
109
}
100
110
101
111
/**
@@ -273,8 +283,6 @@ TypeBasedMultiplexer typeMultiplexer(final String keyOfObj, final Object obj) {
273
283
return new TypeBasedMultiplexer (keyOfObj , obj );
274
284
}
275
285
276
- private final Collection <ReferenceSchema .Builder > rootReferences ;
277
-
278
286
private String id = null ;
279
287
280
288
private final JSONObject schemaJson ;
@@ -283,17 +291,19 @@ TypeBasedMultiplexer typeMultiplexer(final String keyOfObj, final Object obj) {
283
291
284
292
private final HttpClient httpClient ;
285
293
294
+ private final Map <String , ReferenceSchema .Builder > pointerSchemas ;
295
+
286
296
/**
287
297
* Constructor.
288
298
*/
289
299
public SchemaLoader (final String id , final JSONObject schemaJson ,
290
- final JSONObject rootSchemaJson , final Collection < ReferenceSchema .Builder > rootReferences ,
300
+ final JSONObject rootSchemaJson , final Map < String , ReferenceSchema .Builder > pointerSchemas ,
291
301
final HttpClient httpClient ) {
292
302
this .schemaJson = Objects .requireNonNull (schemaJson , "schemaJson cannot be null" );
293
303
this .rootSchemaJson = Objects .requireNonNull (rootSchemaJson , "rootSchemaJson cannot be null" );
294
304
this .id = id ;
295
- this .rootReferences = rootReferences == null ? new ArrayList <>() : rootReferences ;
296
305
this .httpClient = Objects .requireNonNull (httpClient , "httpClient cannot be null" );
306
+ this .pointerSchemas = pointerSchemas ;
297
307
}
298
308
299
309
private void addDependencies (final Builder builder , final JSONObject deps ) {
@@ -486,7 +496,8 @@ private EnumSchema.Builder buildEnumSchema() {
486
496
}
487
497
488
498
private Schema .Builder <?> loadChild (final JSONObject childJson ) {
489
- return new SchemaLoader (id , childJson , rootSchemaJson , rootReferences , httpClient ).load ();
499
+ return new SchemaLoader (id , childJson , rootSchemaJson , pointerSchemas ,
500
+ httpClient ).load ();
490
501
}
491
502
492
503
private Schema .Builder <?> loadForExplicitType (final String typeString ) {
@@ -514,21 +525,28 @@ private Schema.Builder<?> loadForExplicitType(final String typeString) {
514
525
* Returns a schema builder instance after looking up the JSON pointer.
515
526
*/
516
527
private Schema .Builder <?> lookupReference (final String relPointerString ) {
517
- if ("#" .equals (relPointerString )) {
518
- ReferenceSchema .Builder rval = new ReferenceSchema .Builder ();
519
- rootReferences .add (rval );
520
- return rval ;
521
- }
522
528
JSONPointer pointer ;
523
529
String absPointerString = id + relPointerString ;
524
530
if (absPointerString .startsWith ("#" )) {
525
- pointer = JSONPointer .forDocument (rootSchemaJson , absPointerString );
531
+ if (pointerSchemas .containsKey (absPointerString )) {
532
+ return pointerSchemas .get (absPointerString );
533
+ } else {
534
+ ReferenceSchema .Builder refBuilder = ReferenceSchema .builder ();
535
+ pointerSchemas .put (absPointerString , refBuilder );
536
+ pointer = JSONPointer .forDocument (rootSchemaJson , absPointerString );
537
+ QueryResult result = pointer .query ();
538
+ SchemaLoader childLoader = new SchemaLoader (id , result .getQueryResult (),
539
+ result .getContainingDocument (), pointerSchemas , httpClient );
540
+ Schema referredSchema = childLoader .load ().build ();
541
+ refBuilder .build ().setReferredSchema (referredSchema );
542
+ return refBuilder ;
543
+ }
526
544
} else {
527
545
pointer = JSONPointer .forURL (httpClient , absPointerString );
528
546
}
529
547
QueryResult result = pointer .query ();
530
548
return new SchemaLoader (id , result .getQueryResult (), result .getContainingDocument (),
531
- rootReferences , httpClient ).load ();
549
+ pointerSchemas , httpClient ).load ();
532
550
}
533
551
534
552
private boolean schemaHasAnyOf (final Collection <String > propNames ) {
0 commit comments