@@ -67,8 +67,8 @@ class JsonSchema {
67
67
/// Create a schema from a [Map] .
68
68
///
69
69
/// This method is asyncronous to support automatic fetching of sub-[JsonSchema] s for items,
70
- /// properties, and sub-properties of the root schema.
71
- ///
70
+ /// properties, and sub-properties of the root schema.
71
+ ///
72
72
/// TODO: If you want to create a [JsonSchema] ,
73
73
/// first ensure you have fetched all sub-schemas out of band, and use [createSchemaWithProvidedRefs]
74
74
/// instead.
@@ -77,9 +77,9 @@ class JsonSchema {
77
77
static Future <JsonSchema > createSchema (Map data) => new JsonSchema ._fromRootMap (data)._thisCompleter.future;
78
78
79
79
/// Create a schema from a URL.
80
- ///
80
+ ///
81
81
/// This method is asyncronous to support automatic fetching of sub-[JsonSchema] s for items,
82
- /// properties, and sub-properties of the root schema.
82
+ /// properties, and sub-properties of the root schema.
83
83
static Future <JsonSchema > createSchemaFromUrl (String schemaUrl) {
84
84
if (globalCreateJsonSchemaFromUrl == null ) {
85
85
throw new StateError ('no globalCreateJsonSchemaFromUrl defined!' );
@@ -139,7 +139,6 @@ class JsonSchema {
139
139
}
140
140
141
141
Future <JsonSchema > _validateAllPathsAsync () {
142
- // Check all _schemaAssignments for
143
142
if (_root == this ) {
144
143
_schemaAssignments.forEach ((assignment) => assignment ());
145
144
if (_retrievalRequests.isNotEmpty) {
@@ -156,7 +155,9 @@ class JsonSchema {
156
155
Future <JsonSchema > _validateSchemaAsync () {
157
156
// _logger.info('Validating schema $_path'); TODO: re-add logger
158
157
159
- if (_registerSchemaRef (_path, _schemaMap)) {
158
+ _registerSchemaRef (_path, _schemaMap);
159
+
160
+ if (_isRemoteRef (_path, _schemaMap)) {
160
161
// _logger.info('Top level schema is ref: $_schemaRefs'); TODO: re-add logger
161
162
}
162
163
@@ -184,55 +185,136 @@ class JsonSchema {
184
185
return new JsonSchema ._fromMap (_root, schemaDefinition, path);
185
186
}
186
187
187
- // Root Schema Properties
188
+ // --------------------------------------------------------------------------
189
+ // Root Schema Fields
190
+ // --------------------------------------------------------------------------
191
+
192
+ /// The root [JsonSchema] for this [JsonSchema] .
188
193
JsonSchema _root;
194
+
195
+ /// JSON of the [JsonSchema] as a [Map] .
189
196
Map <String , dynamic > _schemaMap = {};
197
+
198
+ /// A [List<JsonSchema>] which the value must conform to all of.
190
199
List <JsonSchema > _allOf = [];
200
+
201
+ /// A [List<JsonSchema>] which the value must conform to at least one of.
191
202
List <JsonSchema > _anyOf = [];
203
+
204
+ /// Default value of the [JsonSchema] .
192
205
dynamic _defaultValue;
206
+
207
+ /// Included [JsonSchema] definitions.
193
208
Map <String , JsonSchema > _definitions = {};
209
+
210
+ /// Description of the [JsonSchema] .
194
211
String _description;
212
+
213
+ /// Possible values of the [JsonSchema] .
195
214
List _enumValues = [];
215
+
216
+ /// Whether the maximum of the [JsonSchema] is exclusive.
196
217
bool _exclusiveMaximum;
218
+
219
+ /// Whether the minumum of the [JsonSchema] is exclusive.
197
220
bool _exclusiveMinimum;
198
221
199
- /// Support for optional formats ( date-time, uri, email, ipv6, hostname)
222
+ /// Pre-defined format (i.e. date-time, email, etc) of the [JsonSchema] value.
200
223
String _format;
224
+
225
+ /// ID of the [JsonSchema] .
201
226
Uri _id;
227
+
228
+ /// Maximum value of the [JsonSchema] value.
202
229
num _maximum;
230
+
231
+ /// Minimum value of the [JsonSchema] value.
203
232
num _minimum;
233
+
234
+ /// Maximum value of the [JsonSchema] value.
204
235
int _maxLength;
236
+
237
+ /// Minimum length of the [JsonSchema] value.
205
238
int _minLength;
239
+
240
+ /// The number which the value of the [JsonSchema] must be a multiple of.
206
241
num _multipleOf;
242
+
243
+ /// A [JsonSchema] which the value must NOT be.
207
244
JsonSchema _notSchema;
245
+
246
+ /// A [List<JsonSchema>] which the value must conform to at least one of.
208
247
List <JsonSchema > _oneOf = [];
248
+
249
+ /// The regular expression the [JsonSchema] value must conform to.
209
250
RegExp _pattern;
251
+
252
+ /// Ref to the URI of the [JsonSchema] .
210
253
String _ref;
254
+
255
+ /// The path of the [JsonSchema] within the root [JsonSchema] .
211
256
String _path;
257
+
258
+ /// Title of the [JsonSchema] .
212
259
String _title;
260
+
261
+ /// List of allowable types for the [JsonSchema] .
213
262
List <SchemaType > _schemaTypeList;
214
263
264
+ // --------------------------------------------------------------------------
215
265
// Schema List Item Related Fields
266
+ // --------------------------------------------------------------------------
267
+
268
+ /// [JsonSchema] definition used to validate items of this schema.
216
269
JsonSchema _items;
270
+
271
+ /// List of [JsonSchema] used to validate items of this schema.
217
272
List <JsonSchema > _itemsList;
218
- dynamic _additionalItems;
273
+
274
+ /// Whether additional items are allowed or the [JsonSchema] they should conform to.
275
+ /* union bool | Map */ dynamic _additionalItems;
276
+
277
+ /// Maimum number of items allowed.
219
278
int _maxItems;
279
+
280
+ /// Maimum number of items allowed.
220
281
int _minItems;
282
+
283
+ /// Whether the items in the list must be unique.
221
284
bool _uniqueItems = false ;
222
285
286
+ // --------------------------------------------------------------------------
223
287
// Schema Sub-Property Related Fields
288
+ // --------------------------------------------------------------------------
289
+
290
+ /// Map of [JsonSchema] s by property key.
224
291
Map <String , JsonSchema > _properties = {};
292
+
293
+ /// Whether additional properties, other than those specified, are allowed.
225
294
bool _additionalProperties;
295
+
296
+ /// [JsonSchema] that additional properties must conform to.
226
297
JsonSchema _additionalPropertiesSchema;
298
+
227
299
Map <String , List <String >> _propertyDependencies = {};
300
+
228
301
Map <String , JsonSchema > _schemaDependencies = {};
302
+
303
+ /// The maximum number of properties allowed.
229
304
int _maxProperties;
305
+
306
+ /// The minimum number of properties allowed.
230
307
int _minProperties = 0 ;
308
+
309
+ /// Map of [JsonSchema] s for properties, based on [RegExp] s keys.
231
310
Map <RegExp , JsonSchema > _patternProperties = {};
311
+
232
312
Map <String , JsonSchema > _refMap = {};
233
313
List <String > _requiredProperties;
234
314
235
- /// Implementation-specific properties:
315
+ // --------------------------------------------------------------------------
316
+ // Implementation Specific Feilds
317
+ // --------------------------------------------------------------------------
236
318
237
319
/// Maps any unsupported top level property to its original value
238
320
Map <String , dynamic > _freeFormMap = {};
@@ -246,7 +328,7 @@ class JsonSchema {
246
328
/// Assignments to call for resolution upon end of parse.
247
329
List _schemaAssignments = [];
248
330
249
- /// For schemas with $ref maps path of schema to $ref path
331
+ /// For schemas with $ref maps, path of schema to $ref path
250
332
Map <String , String > _schemaRefs = {};
251
333
252
334
/// Completer that fires when [this] [JsonSchema] has finished building.
@@ -294,12 +376,7 @@ class JsonSchema {
294
376
};
295
377
296
378
/// Get a nested [JsonSchema] from a path.
297
- JsonSchema resolvePath (String path) {
298
- while (_schemaRefs.containsKey (path)) {
299
- path = _schemaRefs[path];
300
- }
301
- return _refMap[path];
302
- }
379
+ JsonSchema resolvePath (String path) => _resolvePath (path);
303
380
304
381
@override
305
382
String toString () => '${_schemaMap }' ;
@@ -377,7 +454,7 @@ class JsonSchema {
377
454
/// Title of the [JsonSchema] .
378
455
String get title => _title;
379
456
380
- /// TODO
457
+ /// List of allowable types for the [JsonSchema] .
381
458
List <SchemaType > get schemaTypeList => _schemaTypeList;
382
459
383
460
// --------------------------------------------------------------------------
@@ -390,7 +467,7 @@ class JsonSchema {
390
467
/// Ordered list of [JsonSchema] which the value of the same index must conform to.
391
468
List <JsonSchema > get itemsList => _itemsList;
392
469
393
- /// Whether additional items are allowed.
470
+ /// Whether additional items are allowed or the [JsonSchema] they should conform to .
394
471
/* union bool | Map */ dynamic get additionalItems => _additionalItems;
395
472
396
473
/// The maximum number of items allowed.
@@ -475,28 +552,46 @@ class JsonSchema {
475
552
// JSON Schema Internal Operations
476
553
// --------------------------------------------------------------------------
477
554
478
- bool _registerSchemaRef (String path, dynamic schemaDefinition) {
479
- if (schemaDefinition is Map ) {
480
- final dynamic ref = schemaDefinition[r'$ref' ];
481
- if (ref != null ) {
482
- if (ref is String ) {
483
- // _logger.info('Linking $path to $ref'); TODO: re-add logger
484
- _schemaRefs[path] = ref;
485
- return true ;
486
- } else {
487
- throw FormatExceptions .string ('\$ ref' , ref);
488
- }
489
- }
555
+ /// Function to determine whether a given [schemaDefinition] is a remote $ref.
556
+ bool _isRemoteRef (String path, dynamic schemaDefinition) {
557
+ final Map schemaDefinitionMap = TypeValidators .object (path, schemaDefinition);
558
+ final dynamic ref = schemaDefinitionMap[r'$ref' ];
559
+ if (ref != null ) {
560
+ TypeValidators .nonEmptyString (r'$ref' , ref);
561
+ // If the ref begins with "#" it is a local ref, so we return false.
562
+ if (ref[0 ] != '#' ) return false ;
563
+ return true ;
490
564
}
491
565
return false ;
492
566
}
493
567
568
+ /// Checks if a [schemaDefinition] has a $ref.
569
+ /// If it does, it adds the $ref to [_shemaRefs] at the path key and returns true.
570
+ void _registerSchemaRef (String path, dynamic schemaDefinition) {
571
+ final Map schemaDefinitionMap = TypeValidators .object (path, schemaDefinition);
572
+ final dynamic ref = schemaDefinitionMap[r'$ref' ];
573
+ if (_isRemoteRef (path, schemaDefinition)) {
574
+ // _logger.info('Linking $path to $ref'); TODO: re-add logger
575
+ _schemaRefs[path] = ref;
576
+ }
577
+ }
578
+
494
579
/// Add a ref'd JsonSchema to the map of available Schemas.
495
580
_addSchema (String path, JsonSchema schema) => _refMap[path] = schema;
496
581
582
+ // Create a [JsonSchema] from a sub-schema of the root.
497
583
_makeSchema (String path, dynamic schema, SchemaAssigner assigner) {
498
584
if (schema is ! Map ) throw FormatExceptions .schema (path, schema);
499
- if (_registerSchemaRef (path, schema)) {
585
+
586
+ _registerSchemaRef (path, schema);
587
+
588
+ final isRemoteReference = _isRemoteRef (path, schema);
589
+ final isPathLocal = path[0 ] == '#' ;
590
+
591
+ /// If this sub-schema is a ref within the root schema,
592
+ /// add it to the map of local schema assignments.
593
+ /// Otherwise, call the assigner function and create a new [JsonSchema] .
594
+ if (isRemoteReference && isPathLocal) {
500
595
_schemaAssignments.add (() => assigner (_resolvePath (path)));
501
596
} else {
502
597
assigner (_createSubSchema (schema, path));
@@ -578,7 +673,9 @@ class JsonSchema {
578
673
_ref = TypeValidators .nonEmptyString (r'$ref' , value);
579
674
if (_ref[0 ] != '#' ) {
580
675
final refSchemaFuture = createSchemaFromUrl (_ref).then ((schema) => _addSchema (_ref, schema));
581
- _retrievalRequests.add (refSchemaFuture);
676
+
677
+ /// Always add sub-schema retrieval requests to the [_root] , as this is where the promise resolves.
678
+ _root._retrievalRequests.add (refSchemaFuture);
582
679
}
583
680
}
584
681
0 commit comments