z-schema 6.0.2 → 7.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -134
- package/bin/z-schema +128 -124
- package/cjs/ZSchema.d.ts +227 -0
- package/cjs/ZSchema.js +13785 -0
- package/dist/Errors.js +50 -0
- package/dist/FormatValidators.js +136 -0
- package/{src → dist}/JsonValidation.js +184 -213
- package/dist/Report.js +220 -0
- package/{src → dist}/SchemaCache.js +67 -82
- package/{src → dist}/SchemaCompilation.js +89 -129
- package/dist/SchemaValidation.js +631 -0
- package/{src → dist}/Utils.js +96 -104
- package/dist/ZSchema.js +365 -0
- package/dist/index.js +2 -0
- package/dist/schemas/hyper-schema.json +156 -0
- package/dist/schemas/schema.json +151 -0
- package/dist/types/Errors.d.ts +44 -0
- package/dist/types/FormatValidators.d.ts +12 -0
- package/dist/types/JsonValidation.d.ts +37 -0
- package/dist/types/Report.d.ts +87 -0
- package/dist/types/SchemaCache.d.ts +26 -0
- package/dist/types/SchemaCompilation.d.ts +1 -0
- package/dist/types/SchemaValidation.d.ts +6 -0
- package/dist/types/Utils.d.ts +64 -0
- package/dist/types/ZSchema.d.ts +97 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +59 -45
- package/src/Errors.ts +56 -0
- package/src/FormatValidators.ts +136 -0
- package/src/JsonValidation.ts +624 -0
- package/src/Report.ts +337 -0
- package/src/SchemaCache.ts +189 -0
- package/src/SchemaCompilation.ts +293 -0
- package/src/SchemaValidation.ts +629 -0
- package/src/Utils.ts +286 -0
- package/src/ZSchema.ts +467 -0
- package/src/index.ts +3 -0
- package/src/schemas/_ +0 -0
- package/umd/ZSchema.js +13791 -0
- package/umd/ZSchema.min.js +1 -0
- package/dist/ZSchema-browser-min.js +0 -2
- package/dist/ZSchema-browser-min.js.map +0 -1
- package/dist/ZSchema-browser-test.js +0 -32247
- package/dist/ZSchema-browser.js +0 -12745
- package/index.d.ts +0 -175
- package/src/Errors.js +0 -60
- package/src/FormatValidators.js +0 -129
- package/src/Polyfills.js +0 -16
- package/src/Report.js +0 -299
- package/src/SchemaValidation.js +0 -619
- package/src/ZSchema.js +0 -409
|
@@ -1,47 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var shouldSkipValidate = function (options, errors) {
|
|
8
|
-
return options &&
|
|
1
|
+
import { FormatValidators } from './FormatValidators.js';
|
|
2
|
+
import { Report } from './Report.js';
|
|
3
|
+
import * as Utils from './Utils.js';
|
|
4
|
+
const shouldSkipValidate = function (options, errors) {
|
|
5
|
+
return (options &&
|
|
9
6
|
Array.isArray(options.includeErrors) &&
|
|
10
7
|
options.includeErrors.length > 0 &&
|
|
11
|
-
!errors.some(function (err) {
|
|
8
|
+
!errors.some(function (err) {
|
|
9
|
+
return options.includeErrors.includes(err);
|
|
10
|
+
}));
|
|
12
11
|
};
|
|
13
|
-
|
|
14
|
-
var JsonValidators = {
|
|
12
|
+
export const JsonValidators = {
|
|
15
13
|
multipleOf: function (report, schema, json) {
|
|
16
14
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.2
|
|
17
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
15
|
+
if (shouldSkipValidate(this.validateOptions, ['MULTIPLE_OF'])) {
|
|
18
16
|
return;
|
|
19
17
|
}
|
|
20
|
-
if (typeof json !==
|
|
18
|
+
if (typeof json !== 'number') {
|
|
21
19
|
return;
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
report.addError("MULTIPLE_OF", [json, schema.multipleOf], null, schema);
|
|
21
|
+
const stringMultipleOf = String(schema.multipleOf);
|
|
22
|
+
const scale = Math.pow(10, stringMultipleOf.length - stringMultipleOf.indexOf('.') - 1);
|
|
23
|
+
if (Utils.whatIs((json * scale) / (schema.multipleOf * scale)) !== 'integer') {
|
|
24
|
+
report.addError('MULTIPLE_OF', [json, schema.multipleOf], null, schema);
|
|
28
25
|
}
|
|
29
26
|
},
|
|
30
27
|
maximum: function (report, schema, json) {
|
|
31
28
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.2
|
|
32
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
29
|
+
if (shouldSkipValidate(this.validateOptions, ['MAXIMUM', 'MAXIMUM_EXCLUSIVE'])) {
|
|
33
30
|
return;
|
|
34
31
|
}
|
|
35
|
-
if (typeof json !==
|
|
32
|
+
if (typeof json !== 'number') {
|
|
36
33
|
return;
|
|
37
34
|
}
|
|
38
35
|
if (schema.exclusiveMaximum !== true) {
|
|
39
36
|
if (json > schema.maximum) {
|
|
40
|
-
report.addError(
|
|
37
|
+
report.addError('MAXIMUM', [json, schema.maximum], null, schema);
|
|
41
38
|
}
|
|
42
|
-
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
43
41
|
if (json >= schema.maximum) {
|
|
44
|
-
report.addError(
|
|
42
|
+
report.addError('MAXIMUM_EXCLUSIVE', [json, schema.maximum], null, schema);
|
|
45
43
|
}
|
|
46
44
|
}
|
|
47
45
|
},
|
|
@@ -50,19 +48,20 @@ var JsonValidators = {
|
|
|
50
48
|
},
|
|
51
49
|
minimum: function (report, schema, json) {
|
|
52
50
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.2
|
|
53
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
51
|
+
if (shouldSkipValidate(this.validateOptions, ['MINIMUM', 'MINIMUM_EXCLUSIVE'])) {
|
|
54
52
|
return;
|
|
55
53
|
}
|
|
56
|
-
if (typeof json !==
|
|
54
|
+
if (typeof json !== 'number') {
|
|
57
55
|
return;
|
|
58
56
|
}
|
|
59
57
|
if (schema.exclusiveMinimum !== true) {
|
|
60
58
|
if (json < schema.minimum) {
|
|
61
|
-
report.addError(
|
|
59
|
+
report.addError('MINIMUM', [json, schema.minimum], null, schema);
|
|
62
60
|
}
|
|
63
|
-
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
64
63
|
if (json <= schema.minimum) {
|
|
65
|
-
report.addError(
|
|
64
|
+
report.addError('MINIMUM_EXCLUSIVE', [json, schema.minimum], null, schema);
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
},
|
|
@@ -71,43 +70,43 @@ var JsonValidators = {
|
|
|
71
70
|
},
|
|
72
71
|
maxLength: function (report, schema, json) {
|
|
73
72
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.1.2
|
|
74
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
73
|
+
if (shouldSkipValidate(this.validateOptions, ['MAX_LENGTH'])) {
|
|
75
74
|
return;
|
|
76
75
|
}
|
|
77
|
-
if (typeof json !==
|
|
76
|
+
if (typeof json !== 'string') {
|
|
78
77
|
return;
|
|
79
78
|
}
|
|
80
79
|
if (Utils.ucs2decode(json).length > schema.maxLength) {
|
|
81
|
-
report.addError(
|
|
80
|
+
report.addError('MAX_LENGTH', [json.length, schema.maxLength], null, schema);
|
|
82
81
|
}
|
|
83
82
|
},
|
|
84
83
|
minLength: function (report, schema, json) {
|
|
85
84
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.2.2
|
|
86
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
85
|
+
if (shouldSkipValidate(this.validateOptions, ['MIN_LENGTH'])) {
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
|
-
if (typeof json !==
|
|
88
|
+
if (typeof json !== 'string') {
|
|
90
89
|
return;
|
|
91
90
|
}
|
|
92
91
|
if (Utils.ucs2decode(json).length < schema.minLength) {
|
|
93
|
-
report.addError(
|
|
92
|
+
report.addError('MIN_LENGTH', [json.length, schema.minLength], null, schema);
|
|
94
93
|
}
|
|
95
94
|
},
|
|
96
95
|
pattern: function (report, schema, json) {
|
|
97
96
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.3.2
|
|
98
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
97
|
+
if (shouldSkipValidate(this.validateOptions, ['PATTERN'])) {
|
|
99
98
|
return;
|
|
100
99
|
}
|
|
101
|
-
if (typeof json !==
|
|
100
|
+
if (typeof json !== 'string') {
|
|
102
101
|
return;
|
|
103
102
|
}
|
|
104
103
|
if (RegExp(schema.pattern).test(json) === false) {
|
|
105
|
-
report.addError(
|
|
104
|
+
report.addError('PATTERN', [schema.pattern, json], null, schema);
|
|
106
105
|
}
|
|
107
106
|
},
|
|
108
107
|
additionalItems: function (report, schema, json) {
|
|
109
108
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.2
|
|
110
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
109
|
+
if (shouldSkipValidate(this.validateOptions, ['ARRAY_ADDITIONAL_ITEMS'])) {
|
|
111
110
|
return;
|
|
112
111
|
}
|
|
113
112
|
if (!Array.isArray(json)) {
|
|
@@ -117,91 +116,92 @@ var JsonValidators = {
|
|
|
117
116
|
// the json is valid if its size is less than, or equal to, the size of "items".
|
|
118
117
|
if (schema.additionalItems === false && Array.isArray(schema.items)) {
|
|
119
118
|
if (json.length > schema.items.length) {
|
|
120
|
-
report.addError(
|
|
119
|
+
report.addError('ARRAY_ADDITIONAL_ITEMS', null, null, schema);
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
122
|
},
|
|
124
|
-
items: function () {
|
|
123
|
+
items: function () {
|
|
124
|
+
/*report, schema, json*/
|
|
125
125
|
// covered in additionalItems
|
|
126
126
|
},
|
|
127
127
|
maxItems: function (report, schema, json) {
|
|
128
128
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.2.2
|
|
129
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
129
|
+
if (shouldSkipValidate(this.validateOptions, ['ARRAY_LENGTH_LONG'])) {
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
if (!Array.isArray(json)) {
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
if (json.length > schema.maxItems) {
|
|
136
|
-
report.addError(
|
|
136
|
+
report.addError('ARRAY_LENGTH_LONG', [json.length, schema.maxItems], null, schema);
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
139
|
minItems: function (report, schema, json) {
|
|
140
140
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.3.2
|
|
141
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
141
|
+
if (shouldSkipValidate(this.validateOptions, ['ARRAY_LENGTH_SHORT'])) {
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
if (!Array.isArray(json)) {
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
if (json.length < schema.minItems) {
|
|
148
|
-
report.addError(
|
|
148
|
+
report.addError('ARRAY_LENGTH_SHORT', [json.length, schema.minItems], null, schema);
|
|
149
149
|
}
|
|
150
150
|
},
|
|
151
151
|
uniqueItems: function (report, schema, json) {
|
|
152
152
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.4.2
|
|
153
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
153
|
+
if (shouldSkipValidate(this.validateOptions, ['ARRAY_UNIQUE'])) {
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
if (!Array.isArray(json)) {
|
|
157
157
|
return;
|
|
158
158
|
}
|
|
159
159
|
if (schema.uniqueItems === true) {
|
|
160
|
-
|
|
160
|
+
const matches = [];
|
|
161
161
|
if (Utils.isUniqueArray(json, matches) === false) {
|
|
162
|
-
report.addError(
|
|
162
|
+
report.addError('ARRAY_UNIQUE', matches, null, schema);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
maxProperties: function (report, schema, json) {
|
|
167
167
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.1.2
|
|
168
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
168
|
+
if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MAXIMUM'])) {
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
|
-
if (Utils.whatIs(json) !==
|
|
171
|
+
if (Utils.whatIs(json) !== 'object') {
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
174
|
-
|
|
174
|
+
const keysCount = Object.keys(json).length;
|
|
175
175
|
if (keysCount > schema.maxProperties) {
|
|
176
|
-
report.addError(
|
|
176
|
+
report.addError('OBJECT_PROPERTIES_MAXIMUM', [keysCount, schema.maxProperties], null, schema);
|
|
177
177
|
}
|
|
178
178
|
},
|
|
179
179
|
minProperties: function (report, schema, json) {
|
|
180
180
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.2.2
|
|
181
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
181
|
+
if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MINIMUM'])) {
|
|
182
182
|
return;
|
|
183
183
|
}
|
|
184
|
-
if (Utils.whatIs(json) !==
|
|
184
|
+
if (Utils.whatIs(json) !== 'object') {
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
|
-
|
|
187
|
+
const keysCount = Object.keys(json).length;
|
|
188
188
|
if (keysCount < schema.minProperties) {
|
|
189
|
-
report.addError(
|
|
189
|
+
report.addError('OBJECT_PROPERTIES_MINIMUM', [keysCount, schema.minProperties], null, schema);
|
|
190
190
|
}
|
|
191
191
|
},
|
|
192
192
|
required: function (report, schema, json) {
|
|
193
193
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.3.2
|
|
194
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
194
|
+
if (shouldSkipValidate(this.validateOptions, ['OBJECT_MISSING_REQUIRED_PROPERTY'])) {
|
|
195
195
|
return;
|
|
196
196
|
}
|
|
197
|
-
if (Utils.whatIs(json) !==
|
|
197
|
+
if (Utils.whatIs(json) !== 'object') {
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
|
-
|
|
200
|
+
let idx = schema.required.length;
|
|
201
201
|
while (idx--) {
|
|
202
|
-
|
|
202
|
+
const requiredPropertyName = schema.required[idx];
|
|
203
203
|
if (json[requiredPropertyName] === undefined) {
|
|
204
|
-
report.addError(
|
|
204
|
+
report.addError('OBJECT_MISSING_REQUIRED_PROPERTY', [requiredPropertyName], null, schema);
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
},
|
|
@@ -219,28 +219,28 @@ var JsonValidators = {
|
|
|
219
219
|
},
|
|
220
220
|
properties: function (report, schema, json) {
|
|
221
221
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.2
|
|
222
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
222
|
+
if (shouldSkipValidate(this.validateOptions, ['OBJECT_ADDITIONAL_PROPERTIES'])) {
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
|
-
if (Utils.whatIs(json) !==
|
|
225
|
+
if (Utils.whatIs(json) !== 'object') {
|
|
226
226
|
return;
|
|
227
227
|
}
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
const properties = schema.properties !== undefined ? schema.properties : {};
|
|
229
|
+
const patternProperties = schema.patternProperties !== undefined ? schema.patternProperties : {};
|
|
230
230
|
if (schema.additionalProperties === false) {
|
|
231
231
|
// The property set of the json to validate.
|
|
232
|
-
|
|
232
|
+
let s = Object.keys(json);
|
|
233
233
|
// The property set from "properties".
|
|
234
|
-
|
|
234
|
+
const p = Object.keys(properties);
|
|
235
235
|
// The property set from "patternProperties".
|
|
236
|
-
|
|
236
|
+
const pp = Object.keys(patternProperties);
|
|
237
237
|
// remove from "s" all elements of "p", if any;
|
|
238
238
|
s = Utils.difference(s, p);
|
|
239
239
|
// for each regex in "pp", remove all elements of "s" which this regex matches.
|
|
240
|
-
|
|
240
|
+
let idx = pp.length;
|
|
241
241
|
while (idx--) {
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
const regExp = RegExp(pp[idx]);
|
|
243
|
+
let idx2 = s.length;
|
|
244
244
|
while (idx2--) {
|
|
245
245
|
if (regExp.test(s[idx2]) === true) {
|
|
246
246
|
s.splice(idx2, 1);
|
|
@@ -250,19 +250,19 @@ var JsonValidators = {
|
|
|
250
250
|
// Validation of the json succeeds if, after these two steps, set "s" is empty.
|
|
251
251
|
if (s.length > 0) {
|
|
252
252
|
// assumeAdditional can be an array of allowed properties
|
|
253
|
-
|
|
253
|
+
let idx3 = this.options.assumeAdditional.length;
|
|
254
254
|
if (idx3) {
|
|
255
255
|
while (idx3--) {
|
|
256
|
-
|
|
256
|
+
const io = s.indexOf(this.options.assumeAdditional[idx3]);
|
|
257
257
|
if (io !== -1) {
|
|
258
258
|
s.splice(io, 1);
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
|
|
262
|
+
let idx4 = s.length;
|
|
263
263
|
if (idx4) {
|
|
264
264
|
while (idx4--) {
|
|
265
|
-
report.addError(
|
|
265
|
+
report.addError('OBJECT_ADDITIONAL_PROPERTIES', [s[idx4]], null, schema);
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
}
|
|
@@ -270,31 +270,31 @@ var JsonValidators = {
|
|
|
270
270
|
},
|
|
271
271
|
dependencies: function (report, schema, json) {
|
|
272
272
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.5.2
|
|
273
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
273
|
+
if (shouldSkipValidate(this.validateOptions, ['OBJECT_DEPENDENCY_KEY'])) {
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
|
-
if (Utils.whatIs(json) !==
|
|
276
|
+
if (Utils.whatIs(json) !== 'object') {
|
|
277
277
|
return;
|
|
278
278
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
idx = keys.length;
|
|
282
|
-
|
|
279
|
+
const keys = Object.keys(schema.dependencies);
|
|
280
|
+
let idx = keys.length;
|
|
283
281
|
while (idx--) {
|
|
284
282
|
// iterate all dependencies
|
|
285
|
-
|
|
283
|
+
const dependencyName = keys[idx];
|
|
286
284
|
if (json[dependencyName]) {
|
|
287
|
-
|
|
288
|
-
if (Utils.whatIs(dependencyDefinition) ===
|
|
285
|
+
const dependencyDefinition = schema.dependencies[dependencyName];
|
|
286
|
+
if (Utils.whatIs(dependencyDefinition) === 'object') {
|
|
289
287
|
// if dependency is a schema, validate against this schema
|
|
290
|
-
|
|
291
|
-
}
|
|
288
|
+
validate.call(this, report, dependencyDefinition, json);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
// Array
|
|
292
292
|
// if dependency is an array, object needs to have all properties in this array
|
|
293
|
-
|
|
293
|
+
let idx2 = dependencyDefinition.length;
|
|
294
294
|
while (idx2--) {
|
|
295
|
-
|
|
295
|
+
const requiredPropertyName = dependencyDefinition[idx2];
|
|
296
296
|
if (json[requiredPropertyName] === undefined) {
|
|
297
|
-
report.addError(
|
|
297
|
+
report.addError('OBJECT_DEPENDENCY_KEY', [requiredPropertyName, dependencyName], null, schema);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
}
|
|
@@ -303,47 +303,46 @@ var JsonValidators = {
|
|
|
303
303
|
},
|
|
304
304
|
enum: function (report, schema, json) {
|
|
305
305
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.1.2
|
|
306
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
306
|
+
if (shouldSkipValidate(this.validateOptions, ['ENUM_CASE_MISMATCH', 'ENUM_MISMATCH'])) {
|
|
307
307
|
return;
|
|
308
308
|
}
|
|
309
|
-
|
|
310
|
-
caseInsensitiveMatch = false,
|
|
311
|
-
idx = schema.enum.length;
|
|
309
|
+
let match = false, caseInsensitiveMatch = false, idx = schema.enum.length;
|
|
312
310
|
while (idx--) {
|
|
313
311
|
if (Utils.areEqual(json, schema.enum[idx])) {
|
|
314
312
|
match = true;
|
|
315
313
|
break;
|
|
316
|
-
}
|
|
314
|
+
}
|
|
315
|
+
else if (Utils.areEqual(json, schema.enum[idx], { caseInsensitiveComparison: true })) {
|
|
317
316
|
caseInsensitiveMatch = true;
|
|
318
317
|
}
|
|
319
318
|
}
|
|
320
|
-
|
|
321
319
|
if (match === false) {
|
|
322
|
-
|
|
320
|
+
const error = caseInsensitiveMatch && this.options.enumCaseInsensitiveComparison ? 'ENUM_CASE_MISMATCH' : 'ENUM_MISMATCH';
|
|
323
321
|
report.addError(error, [json], null, schema);
|
|
324
322
|
}
|
|
325
323
|
},
|
|
326
324
|
type: function (report, schema, json) {
|
|
327
325
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.2
|
|
328
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
326
|
+
if (shouldSkipValidate(this.validateOptions, ['INVALID_TYPE'])) {
|
|
329
327
|
return;
|
|
330
328
|
}
|
|
331
|
-
|
|
332
|
-
if (typeof schema.type ===
|
|
333
|
-
if (jsonType !== schema.type && (jsonType !==
|
|
334
|
-
report.addError(
|
|
329
|
+
const jsonType = Utils.whatIs(json);
|
|
330
|
+
if (typeof schema.type === 'string') {
|
|
331
|
+
if (jsonType !== schema.type && (jsonType !== 'integer' || schema.type !== 'number')) {
|
|
332
|
+
report.addError('INVALID_TYPE', [schema.type, jsonType], null, schema);
|
|
335
333
|
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
if (schema.type.indexOf(jsonType) === -1 && (jsonType !== 'integer' || schema.type.indexOf('number') === -1)) {
|
|
337
|
+
report.addError('INVALID_TYPE', [schema.type, jsonType], null, schema);
|
|
339
338
|
}
|
|
340
339
|
}
|
|
341
340
|
},
|
|
342
341
|
allOf: function (report, schema, json) {
|
|
343
342
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.3.2
|
|
344
|
-
|
|
343
|
+
let idx = schema.allOf.length;
|
|
345
344
|
while (idx--) {
|
|
346
|
-
|
|
345
|
+
const validateResult = validate.call(this, report, schema.allOf[idx], json);
|
|
347
346
|
if (this.options.breakOnFirstError && validateResult === false) {
|
|
348
347
|
break;
|
|
349
348
|
}
|
|
@@ -351,274 +350,246 @@ var JsonValidators = {
|
|
|
351
350
|
},
|
|
352
351
|
anyOf: function (report, schema, json) {
|
|
353
352
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.4.2
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
353
|
+
const subReports = [];
|
|
354
|
+
let passed = false;
|
|
355
|
+
let idx = schema.anyOf.length;
|
|
358
356
|
while (idx-- && passed === false) {
|
|
359
|
-
|
|
357
|
+
const subReport = new Report(report);
|
|
360
358
|
subReports.push(subReport);
|
|
361
|
-
passed =
|
|
359
|
+
passed = validate.call(this, subReport, schema.anyOf[idx], json);
|
|
362
360
|
}
|
|
363
|
-
|
|
364
361
|
if (passed === false) {
|
|
365
|
-
report.addError(
|
|
362
|
+
report.addError('ANY_OF_MISSING', undefined, subReports, schema);
|
|
366
363
|
}
|
|
367
364
|
},
|
|
368
365
|
oneOf: function (report, schema, json) {
|
|
369
366
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.5.2
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
367
|
+
let passes = 0;
|
|
368
|
+
const subReports = [];
|
|
369
|
+
let idx = schema.oneOf.length;
|
|
374
370
|
while (idx--) {
|
|
375
|
-
|
|
371
|
+
const subReport = new Report(report, { maxErrors: 1 });
|
|
376
372
|
subReports.push(subReport);
|
|
377
|
-
if (
|
|
373
|
+
if (validate.call(this, subReport, schema.oneOf[idx], json) === true) {
|
|
378
374
|
passes++;
|
|
379
375
|
}
|
|
380
376
|
}
|
|
381
|
-
|
|
382
377
|
if (passes === 0) {
|
|
383
|
-
report.addError(
|
|
384
|
-
}
|
|
385
|
-
|
|
378
|
+
report.addError('ONE_OF_MISSING', undefined, subReports, schema);
|
|
379
|
+
}
|
|
380
|
+
else if (passes > 1) {
|
|
381
|
+
report.addError('ONE_OF_MULTIPLE', null, null, schema);
|
|
386
382
|
}
|
|
387
383
|
},
|
|
388
384
|
not: function (report, schema, json) {
|
|
389
385
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.2
|
|
390
|
-
|
|
391
|
-
if (
|
|
392
|
-
report.addError(
|
|
386
|
+
const subReport = new Report(report);
|
|
387
|
+
if (validate.call(this, subReport, schema.not, json) === true) {
|
|
388
|
+
report.addError('NOT_PASSED', null, null, schema);
|
|
393
389
|
}
|
|
394
390
|
},
|
|
395
|
-
definitions: function () {
|
|
391
|
+
definitions: function () {
|
|
392
|
+
/*report, schema, json*/
|
|
396
393
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.2
|
|
397
394
|
// nothing to do here
|
|
398
395
|
},
|
|
399
396
|
format: function (report, schema, json) {
|
|
400
397
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.7.2
|
|
401
|
-
|
|
402
|
-
if (typeof formatValidatorFn ===
|
|
403
|
-
if (shouldSkipValidate(this.validateOptions, [
|
|
398
|
+
const formatValidatorFn = FormatValidators[schema.format];
|
|
399
|
+
if (typeof formatValidatorFn === 'function') {
|
|
400
|
+
if (shouldSkipValidate(this.validateOptions, ['INVALID_FORMAT'])) {
|
|
404
401
|
return;
|
|
405
402
|
}
|
|
406
|
-
if (report.hasError(
|
|
403
|
+
if (report.hasError('INVALID_TYPE', [schema.type, Utils.whatIs(json)])) {
|
|
407
404
|
return;
|
|
408
405
|
}
|
|
409
406
|
if (formatValidatorFn.length === 2) {
|
|
410
407
|
// async - need to clone the path here, because it will change by the time async function reports back
|
|
411
|
-
|
|
408
|
+
const pathBeforeAsync = Utils.clone(report.path);
|
|
412
409
|
report.addAsyncTask(formatValidatorFn, [json], function (result) {
|
|
413
410
|
if (result !== true) {
|
|
414
|
-
|
|
411
|
+
const backup = report.path;
|
|
415
412
|
report.path = pathBeforeAsync;
|
|
416
|
-
report.addError(
|
|
413
|
+
report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
|
|
417
414
|
report.path = backup;
|
|
418
415
|
}
|
|
419
416
|
});
|
|
420
|
-
}
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
421
419
|
// sync
|
|
422
420
|
if (formatValidatorFn.call(this, json) !== true) {
|
|
423
|
-
report.addError(
|
|
421
|
+
report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
|
|
424
422
|
}
|
|
425
423
|
}
|
|
426
|
-
} else if (this.options.ignoreUnknownFormats !== true) {
|
|
427
|
-
report.addError("UNKNOWN_FORMAT", [schema.format], null, schema);
|
|
428
424
|
}
|
|
429
|
-
|
|
425
|
+
else if (this.options.ignoreUnknownFormats !== true) {
|
|
426
|
+
report.addError('UNKNOWN_FORMAT', [schema.format], null, schema);
|
|
427
|
+
}
|
|
428
|
+
},
|
|
430
429
|
};
|
|
431
|
-
|
|
432
|
-
var recurseArray = function (report, schema, json) {
|
|
430
|
+
const recurseArray = function (report, schema, json) {
|
|
433
431
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.2
|
|
434
|
-
|
|
435
|
-
var idx = json.length;
|
|
436
|
-
|
|
432
|
+
let idx = json.length;
|
|
437
433
|
// If "items" is an array, this situation, the schema depends on the index:
|
|
438
434
|
// if the index is less than, or equal to, the size of "items",
|
|
439
435
|
// the child instance must be valid against the corresponding schema in the "items" array;
|
|
440
436
|
// otherwise, it must be valid against the schema defined by "additionalItems".
|
|
441
437
|
if (Array.isArray(schema.items)) {
|
|
442
|
-
|
|
443
438
|
while (idx--) {
|
|
444
439
|
// equal to doesn't make sense here
|
|
445
440
|
if (idx < schema.items.length) {
|
|
446
441
|
report.path.push(idx);
|
|
447
|
-
|
|
442
|
+
validate.call(this, report, schema.items[idx], json[idx]);
|
|
448
443
|
report.path.pop();
|
|
449
|
-
}
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
450
446
|
// might be boolean, so check that it's an object
|
|
451
|
-
if (typeof schema.additionalItems ===
|
|
447
|
+
if (typeof schema.additionalItems === 'object') {
|
|
452
448
|
report.path.push(idx);
|
|
453
|
-
|
|
449
|
+
validate.call(this, report, schema.additionalItems, json[idx]);
|
|
454
450
|
report.path.pop();
|
|
455
451
|
}
|
|
456
452
|
}
|
|
457
453
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
454
|
+
}
|
|
455
|
+
else if (typeof schema.items === 'object') {
|
|
461
456
|
// If items is a schema, then the child instance must be valid against this schema,
|
|
462
457
|
// regardless of its index, and regardless of the value of "additionalItems".
|
|
463
458
|
while (idx--) {
|
|
464
459
|
report.path.push(idx);
|
|
465
|
-
|
|
460
|
+
validate.call(this, report, schema.items, json[idx]);
|
|
466
461
|
report.path.pop();
|
|
467
462
|
}
|
|
468
|
-
|
|
469
463
|
}
|
|
470
464
|
};
|
|
471
|
-
|
|
472
|
-
var recurseObject = function (report, schema, json) {
|
|
465
|
+
const recurseObject = function (report, schema, json) {
|
|
473
466
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.3
|
|
474
|
-
|
|
475
467
|
// If "additionalProperties" is absent, it is considered present with an empty schema as a value.
|
|
476
468
|
// In addition, boolean value true is considered equivalent to an empty schema.
|
|
477
|
-
|
|
469
|
+
let additionalProperties = schema.additionalProperties;
|
|
478
470
|
if (additionalProperties === true || additionalProperties === undefined) {
|
|
479
471
|
additionalProperties = {};
|
|
480
472
|
}
|
|
481
|
-
|
|
482
473
|
// p - The property set from "properties".
|
|
483
|
-
|
|
484
|
-
|
|
474
|
+
const p = schema.properties ? Object.keys(schema.properties) : [];
|
|
485
475
|
// pp - The property set from "patternProperties". Elements of this set will be called regexes for convenience.
|
|
486
|
-
|
|
487
|
-
|
|
476
|
+
const pp = schema.patternProperties ? Object.keys(schema.patternProperties) : [];
|
|
488
477
|
// m - The property name of the child.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
478
|
+
const keys = Object.keys(json);
|
|
479
|
+
let idx = keys.length;
|
|
492
480
|
while (idx--) {
|
|
493
|
-
|
|
494
|
-
propertyValue = json[m];
|
|
495
|
-
|
|
481
|
+
const m = keys[idx], propertyValue = json[m];
|
|
496
482
|
// s - The set of schemas for the child instance.
|
|
497
|
-
|
|
498
|
-
|
|
483
|
+
const s = [];
|
|
499
484
|
// 1. If set "p" contains value "m", then the corresponding schema in "properties" is added to "s".
|
|
500
485
|
if (p.indexOf(m) !== -1) {
|
|
501
486
|
s.push(schema.properties[m]);
|
|
502
487
|
}
|
|
503
|
-
|
|
504
488
|
// 2. For each regex in "pp", if it matches "m" successfully, the corresponding schema in "patternProperties" is added to "s".
|
|
505
|
-
|
|
489
|
+
let idx2 = pp.length;
|
|
506
490
|
while (idx2--) {
|
|
507
|
-
|
|
491
|
+
const regexString = pp[idx2];
|
|
508
492
|
if (RegExp(regexString).test(m) === true) {
|
|
509
493
|
s.push(schema.patternProperties[regexString]);
|
|
510
494
|
}
|
|
511
495
|
}
|
|
512
|
-
|
|
513
496
|
// 3. The schema defined by "additionalProperties" is added to "s" if and only if, at this stage, "s" is empty.
|
|
514
497
|
if (s.length === 0 && additionalProperties !== false) {
|
|
515
498
|
s.push(additionalProperties);
|
|
516
499
|
}
|
|
517
|
-
|
|
518
500
|
// we are passing tests even without this assert because this is covered by properties check
|
|
519
501
|
// if s is empty in this stage, no additionalProperties are allowed
|
|
520
502
|
// report.expect(s.length !== 0, 'E001', m);
|
|
521
|
-
|
|
522
503
|
// Instance property value must pass all schemas from s
|
|
523
504
|
idx2 = s.length;
|
|
524
505
|
while (idx2--) {
|
|
525
506
|
report.path.push(m);
|
|
526
|
-
|
|
507
|
+
validate.call(this, report, s[idx2], propertyValue);
|
|
527
508
|
report.path.pop();
|
|
528
509
|
}
|
|
529
510
|
}
|
|
530
511
|
};
|
|
531
|
-
|
|
532
|
-
exports.JsonValidators = JsonValidators;
|
|
533
|
-
|
|
534
512
|
/**
|
|
535
513
|
*
|
|
536
514
|
* @param {Report} report
|
|
537
515
|
* @param {*} schema
|
|
538
516
|
* @param {*} json
|
|
539
517
|
*/
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
report.commonErrorMessage = "JSON_OBJECT_VALIDATION_FAILED";
|
|
543
|
-
|
|
518
|
+
export function validate(report, schema, json) {
|
|
519
|
+
report.commonErrorMessage = 'JSON_OBJECT_VALIDATION_FAILED';
|
|
544
520
|
// check if schema is an object
|
|
545
|
-
|
|
546
|
-
if (to !==
|
|
547
|
-
report.addError(
|
|
521
|
+
const to = Utils.whatIs(schema);
|
|
522
|
+
if (to !== 'object') {
|
|
523
|
+
report.addError('SCHEMA_NOT_AN_OBJECT', [to], null, schema);
|
|
548
524
|
return false;
|
|
549
525
|
}
|
|
550
|
-
|
|
551
526
|
// check if schema is empty, everything is valid against empty schema
|
|
552
|
-
|
|
527
|
+
let keys = Object.keys(schema);
|
|
553
528
|
if (keys.length === 0) {
|
|
554
529
|
return true;
|
|
555
530
|
}
|
|
556
|
-
|
|
557
531
|
// this method can be called recursively, so we need to remember our root
|
|
558
|
-
|
|
532
|
+
let isRoot = false;
|
|
559
533
|
if (!report.rootSchema) {
|
|
560
534
|
report.rootSchema = schema;
|
|
561
535
|
isRoot = true;
|
|
562
536
|
}
|
|
563
|
-
|
|
564
537
|
// follow schema.$ref keys
|
|
565
538
|
if (schema.$ref !== undefined) {
|
|
566
539
|
// avoid infinite loop with maxRefs
|
|
567
|
-
|
|
540
|
+
let maxRefs = 99;
|
|
568
541
|
while (schema.$ref && maxRefs > 0) {
|
|
569
542
|
if (!schema.__$refResolved) {
|
|
570
|
-
report.addError(
|
|
543
|
+
report.addError('REF_UNRESOLVED', [schema.$ref], null, schema);
|
|
571
544
|
break;
|
|
572
|
-
}
|
|
545
|
+
}
|
|
546
|
+
else if (schema.__$refResolved === schema) {
|
|
573
547
|
break;
|
|
574
|
-
}
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
575
550
|
schema = schema.__$refResolved;
|
|
576
551
|
keys = Object.keys(schema);
|
|
577
552
|
}
|
|
578
553
|
maxRefs--;
|
|
579
554
|
}
|
|
580
555
|
if (maxRefs === 0) {
|
|
581
|
-
throw new Error(
|
|
556
|
+
throw new Error('Circular dependency by $ref references!');
|
|
582
557
|
}
|
|
583
558
|
}
|
|
584
|
-
|
|
585
559
|
// type checking first
|
|
586
|
-
|
|
560
|
+
const jsonType = Utils.whatIs(json);
|
|
587
561
|
if (schema.type) {
|
|
588
|
-
keys.splice(keys.indexOf(
|
|
562
|
+
keys.splice(keys.indexOf('type'), 1);
|
|
589
563
|
JsonValidators.type.call(this, report, schema, json);
|
|
590
564
|
if (report.errors.length && this.options.breakOnFirstError) {
|
|
591
565
|
return false;
|
|
592
566
|
}
|
|
593
567
|
}
|
|
594
|
-
|
|
595
568
|
// now iterate all the keys in schema and execute validation methods
|
|
596
|
-
|
|
569
|
+
let idx = keys.length;
|
|
597
570
|
while (idx--) {
|
|
598
571
|
if (JsonValidators[keys[idx]]) {
|
|
599
572
|
JsonValidators[keys[idx]].call(this, report, schema, json);
|
|
600
|
-
if (report.errors.length && this.options.breakOnFirstError) {
|
|
573
|
+
if (report.errors.length && this.options.breakOnFirstError) {
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
601
576
|
}
|
|
602
577
|
}
|
|
603
|
-
|
|
604
578
|
if (report.errors.length === 0 || this.options.breakOnFirstError === false) {
|
|
605
|
-
if (jsonType ===
|
|
579
|
+
if (jsonType === 'array') {
|
|
606
580
|
recurseArray.call(this, report, schema, json);
|
|
607
|
-
}
|
|
581
|
+
}
|
|
582
|
+
else if (jsonType === 'object') {
|
|
608
583
|
recurseObject.call(this, report, schema, json);
|
|
609
584
|
}
|
|
610
585
|
}
|
|
611
|
-
|
|
612
|
-
if (typeof this.options.customValidator === "function") {
|
|
586
|
+
if (typeof this.options.customValidator === 'function') {
|
|
613
587
|
this.options.customValidator.call(this, report, schema, json);
|
|
614
588
|
}
|
|
615
|
-
|
|
616
589
|
// we don't need the root pointer anymore
|
|
617
590
|
if (isRoot) {
|
|
618
591
|
report.rootSchema = undefined;
|
|
619
592
|
}
|
|
620
|
-
|
|
621
593
|
// return valid just to be able to break at some code points
|
|
622
594
|
return report.errors.length === 0;
|
|
623
|
-
|
|
624
|
-
};
|
|
595
|
+
}
|