z-schema 6.0.1 → 7.0.0-beta.1
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 -137
- package/bin/z-schema +128 -124
- package/dist/Errors.js +50 -0
- package/dist/FormatValidators.js +136 -0
- package/{src → dist}/JsonValidation.js +186 -212
- 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-umd-min.js +1 -0
- package/dist/ZSchema-umd.js +13791 -0
- package/dist/ZSchema.cjs +13785 -0
- package/dist/ZSchema.js +366 -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/package.json +54 -43
- 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 +469 -0
- package/src/schemas/_ +0 -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 -30633
- package/dist/ZSchema-browser.js +0 -13429
- 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,271 +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'])) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (report.hasError('INVALID_TYPE', [schema.type, Utils.whatIs(json)])) {
|
|
404
404
|
return;
|
|
405
405
|
}
|
|
406
406
|
if (formatValidatorFn.length === 2) {
|
|
407
407
|
// async - need to clone the path here, because it will change by the time async function reports back
|
|
408
|
-
|
|
408
|
+
const pathBeforeAsync = Utils.clone(report.path);
|
|
409
409
|
report.addAsyncTask(formatValidatorFn, [json], function (result) {
|
|
410
410
|
if (result !== true) {
|
|
411
|
-
|
|
411
|
+
const backup = report.path;
|
|
412
412
|
report.path = pathBeforeAsync;
|
|
413
|
-
report.addError(
|
|
413
|
+
report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
|
|
414
414
|
report.path = backup;
|
|
415
415
|
}
|
|
416
416
|
});
|
|
417
|
-
}
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
418
419
|
// sync
|
|
419
420
|
if (formatValidatorFn.call(this, json) !== true) {
|
|
420
|
-
report.addError(
|
|
421
|
+
report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
|
|
421
422
|
}
|
|
422
423
|
}
|
|
423
|
-
} else if (this.options.ignoreUnknownFormats !== true) {
|
|
424
|
-
report.addError("UNKNOWN_FORMAT", [schema.format], null, schema);
|
|
425
424
|
}
|
|
426
|
-
|
|
425
|
+
else if (this.options.ignoreUnknownFormats !== true) {
|
|
426
|
+
report.addError('UNKNOWN_FORMAT', [schema.format], null, schema);
|
|
427
|
+
}
|
|
428
|
+
},
|
|
427
429
|
};
|
|
428
|
-
|
|
429
|
-
var recurseArray = function (report, schema, json) {
|
|
430
|
+
const recurseArray = function (report, schema, json) {
|
|
430
431
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.2
|
|
431
|
-
|
|
432
|
-
var idx = json.length;
|
|
433
|
-
|
|
432
|
+
let idx = json.length;
|
|
434
433
|
// If "items" is an array, this situation, the schema depends on the index:
|
|
435
434
|
// if the index is less than, or equal to, the size of "items",
|
|
436
435
|
// the child instance must be valid against the corresponding schema in the "items" array;
|
|
437
436
|
// otherwise, it must be valid against the schema defined by "additionalItems".
|
|
438
437
|
if (Array.isArray(schema.items)) {
|
|
439
|
-
|
|
440
438
|
while (idx--) {
|
|
441
439
|
// equal to doesn't make sense here
|
|
442
440
|
if (idx < schema.items.length) {
|
|
443
441
|
report.path.push(idx);
|
|
444
|
-
|
|
442
|
+
validate.call(this, report, schema.items[idx], json[idx]);
|
|
445
443
|
report.path.pop();
|
|
446
|
-
}
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
447
446
|
// might be boolean, so check that it's an object
|
|
448
|
-
if (typeof schema.additionalItems ===
|
|
447
|
+
if (typeof schema.additionalItems === 'object') {
|
|
449
448
|
report.path.push(idx);
|
|
450
|
-
|
|
449
|
+
validate.call(this, report, schema.additionalItems, json[idx]);
|
|
451
450
|
report.path.pop();
|
|
452
451
|
}
|
|
453
452
|
}
|
|
454
453
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
454
|
+
}
|
|
455
|
+
else if (typeof schema.items === 'object') {
|
|
458
456
|
// If items is a schema, then the child instance must be valid against this schema,
|
|
459
457
|
// regardless of its index, and regardless of the value of "additionalItems".
|
|
460
458
|
while (idx--) {
|
|
461
459
|
report.path.push(idx);
|
|
462
|
-
|
|
460
|
+
validate.call(this, report, schema.items, json[idx]);
|
|
463
461
|
report.path.pop();
|
|
464
462
|
}
|
|
465
|
-
|
|
466
463
|
}
|
|
467
464
|
};
|
|
468
|
-
|
|
469
|
-
var recurseObject = function (report, schema, json) {
|
|
465
|
+
const recurseObject = function (report, schema, json) {
|
|
470
466
|
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.3
|
|
471
|
-
|
|
472
467
|
// If "additionalProperties" is absent, it is considered present with an empty schema as a value.
|
|
473
468
|
// In addition, boolean value true is considered equivalent to an empty schema.
|
|
474
|
-
|
|
469
|
+
let additionalProperties = schema.additionalProperties;
|
|
475
470
|
if (additionalProperties === true || additionalProperties === undefined) {
|
|
476
471
|
additionalProperties = {};
|
|
477
472
|
}
|
|
478
|
-
|
|
479
473
|
// p - The property set from "properties".
|
|
480
|
-
|
|
481
|
-
|
|
474
|
+
const p = schema.properties ? Object.keys(schema.properties) : [];
|
|
482
475
|
// pp - The property set from "patternProperties". Elements of this set will be called regexes for convenience.
|
|
483
|
-
|
|
484
|
-
|
|
476
|
+
const pp = schema.patternProperties ? Object.keys(schema.patternProperties) : [];
|
|
485
477
|
// m - The property name of the child.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
478
|
+
const keys = Object.keys(json);
|
|
479
|
+
let idx = keys.length;
|
|
489
480
|
while (idx--) {
|
|
490
|
-
|
|
491
|
-
propertyValue = json[m];
|
|
492
|
-
|
|
481
|
+
const m = keys[idx], propertyValue = json[m];
|
|
493
482
|
// s - The set of schemas for the child instance.
|
|
494
|
-
|
|
495
|
-
|
|
483
|
+
const s = [];
|
|
496
484
|
// 1. If set "p" contains value "m", then the corresponding schema in "properties" is added to "s".
|
|
497
485
|
if (p.indexOf(m) !== -1) {
|
|
498
486
|
s.push(schema.properties[m]);
|
|
499
487
|
}
|
|
500
|
-
|
|
501
488
|
// 2. For each regex in "pp", if it matches "m" successfully, the corresponding schema in "patternProperties" is added to "s".
|
|
502
|
-
|
|
489
|
+
let idx2 = pp.length;
|
|
503
490
|
while (idx2--) {
|
|
504
|
-
|
|
491
|
+
const regexString = pp[idx2];
|
|
505
492
|
if (RegExp(regexString).test(m) === true) {
|
|
506
493
|
s.push(schema.patternProperties[regexString]);
|
|
507
494
|
}
|
|
508
495
|
}
|
|
509
|
-
|
|
510
496
|
// 3. The schema defined by "additionalProperties" is added to "s" if and only if, at this stage, "s" is empty.
|
|
511
497
|
if (s.length === 0 && additionalProperties !== false) {
|
|
512
498
|
s.push(additionalProperties);
|
|
513
499
|
}
|
|
514
|
-
|
|
515
500
|
// we are passing tests even without this assert because this is covered by properties check
|
|
516
501
|
// if s is empty in this stage, no additionalProperties are allowed
|
|
517
502
|
// report.expect(s.length !== 0, 'E001', m);
|
|
518
|
-
|
|
519
503
|
// Instance property value must pass all schemas from s
|
|
520
504
|
idx2 = s.length;
|
|
521
505
|
while (idx2--) {
|
|
522
506
|
report.path.push(m);
|
|
523
|
-
|
|
507
|
+
validate.call(this, report, s[idx2], propertyValue);
|
|
524
508
|
report.path.pop();
|
|
525
509
|
}
|
|
526
510
|
}
|
|
527
511
|
};
|
|
528
|
-
|
|
529
|
-
exports.JsonValidators = JsonValidators;
|
|
530
|
-
|
|
531
512
|
/**
|
|
532
513
|
*
|
|
533
514
|
* @param {Report} report
|
|
534
515
|
* @param {*} schema
|
|
535
516
|
* @param {*} json
|
|
536
517
|
*/
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
report.commonErrorMessage = "JSON_OBJECT_VALIDATION_FAILED";
|
|
540
|
-
|
|
518
|
+
export function validate(report, schema, json) {
|
|
519
|
+
report.commonErrorMessage = 'JSON_OBJECT_VALIDATION_FAILED';
|
|
541
520
|
// check if schema is an object
|
|
542
|
-
|
|
543
|
-
if (to !==
|
|
544
|
-
report.addError(
|
|
521
|
+
const to = Utils.whatIs(schema);
|
|
522
|
+
if (to !== 'object') {
|
|
523
|
+
report.addError('SCHEMA_NOT_AN_OBJECT', [to], null, schema);
|
|
545
524
|
return false;
|
|
546
525
|
}
|
|
547
|
-
|
|
548
526
|
// check if schema is empty, everything is valid against empty schema
|
|
549
|
-
|
|
527
|
+
let keys = Object.keys(schema);
|
|
550
528
|
if (keys.length === 0) {
|
|
551
529
|
return true;
|
|
552
530
|
}
|
|
553
|
-
|
|
554
531
|
// this method can be called recursively, so we need to remember our root
|
|
555
|
-
|
|
532
|
+
let isRoot = false;
|
|
556
533
|
if (!report.rootSchema) {
|
|
557
534
|
report.rootSchema = schema;
|
|
558
535
|
isRoot = true;
|
|
559
536
|
}
|
|
560
|
-
|
|
561
537
|
// follow schema.$ref keys
|
|
562
538
|
if (schema.$ref !== undefined) {
|
|
563
539
|
// avoid infinite loop with maxRefs
|
|
564
|
-
|
|
540
|
+
let maxRefs = 99;
|
|
565
541
|
while (schema.$ref && maxRefs > 0) {
|
|
566
542
|
if (!schema.__$refResolved) {
|
|
567
|
-
report.addError(
|
|
543
|
+
report.addError('REF_UNRESOLVED', [schema.$ref], null, schema);
|
|
568
544
|
break;
|
|
569
|
-
}
|
|
545
|
+
}
|
|
546
|
+
else if (schema.__$refResolved === schema) {
|
|
570
547
|
break;
|
|
571
|
-
}
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
572
550
|
schema = schema.__$refResolved;
|
|
573
551
|
keys = Object.keys(schema);
|
|
574
552
|
}
|
|
575
553
|
maxRefs--;
|
|
576
554
|
}
|
|
577
555
|
if (maxRefs === 0) {
|
|
578
|
-
throw new Error(
|
|
556
|
+
throw new Error('Circular dependency by $ref references!');
|
|
579
557
|
}
|
|
580
558
|
}
|
|
581
|
-
|
|
582
559
|
// type checking first
|
|
583
|
-
|
|
560
|
+
const jsonType = Utils.whatIs(json);
|
|
584
561
|
if (schema.type) {
|
|
585
|
-
keys.splice(keys.indexOf(
|
|
562
|
+
keys.splice(keys.indexOf('type'), 1);
|
|
586
563
|
JsonValidators.type.call(this, report, schema, json);
|
|
587
564
|
if (report.errors.length && this.options.breakOnFirstError) {
|
|
588
565
|
return false;
|
|
589
566
|
}
|
|
590
567
|
}
|
|
591
|
-
|
|
592
568
|
// now iterate all the keys in schema and execute validation methods
|
|
593
|
-
|
|
569
|
+
let idx = keys.length;
|
|
594
570
|
while (idx--) {
|
|
595
571
|
if (JsonValidators[keys[idx]]) {
|
|
596
572
|
JsonValidators[keys[idx]].call(this, report, schema, json);
|
|
597
|
-
if (report.errors.length && this.options.breakOnFirstError) {
|
|
573
|
+
if (report.errors.length && this.options.breakOnFirstError) {
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
598
576
|
}
|
|
599
577
|
}
|
|
600
|
-
|
|
601
578
|
if (report.errors.length === 0 || this.options.breakOnFirstError === false) {
|
|
602
|
-
if (jsonType ===
|
|
579
|
+
if (jsonType === 'array') {
|
|
603
580
|
recurseArray.call(this, report, schema, json);
|
|
604
|
-
}
|
|
581
|
+
}
|
|
582
|
+
else if (jsonType === 'object') {
|
|
605
583
|
recurseObject.call(this, report, schema, json);
|
|
606
584
|
}
|
|
607
585
|
}
|
|
608
|
-
|
|
609
|
-
if (typeof this.options.customValidator === "function") {
|
|
586
|
+
if (typeof this.options.customValidator === 'function') {
|
|
610
587
|
this.options.customValidator.call(this, report, schema, json);
|
|
611
588
|
}
|
|
612
|
-
|
|
613
589
|
// we don't need the root pointer anymore
|
|
614
590
|
if (isRoot) {
|
|
615
591
|
report.rootSchema = undefined;
|
|
616
592
|
}
|
|
617
|
-
|
|
618
593
|
// return valid just to be able to break at some code points
|
|
619
594
|
return report.errors.length === 0;
|
|
620
|
-
|
|
621
|
-
};
|
|
595
|
+
}
|