z-schema 12.0.4 → 12.1.0
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/bin/z-schema +7 -2
- package/cjs/index.d.ts +541 -530
- package/cjs/index.js +3963 -7740
- package/dist/errors.d.mts +64 -0
- package/dist/errors.mjs +67 -0
- package/dist/format-validators.d.mts +14 -0
- package/dist/format-validators.mjs +261 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +7 -0
- package/dist/json-schema-versions.d.mts +137 -0
- package/dist/json-schema-versions.mjs +11 -0
- package/dist/json-schema.d.mts +61 -0
- package/dist/json-schema.mjs +53 -0
- package/dist/json-validation.mjs +441 -0
- package/dist/report.d.mts +97 -0
- package/dist/report.mjs +194 -0
- package/dist/schema-cache.d.mts +23 -0
- package/dist/schema-cache.mjs +144 -0
- package/dist/schema-compiler.d.mts +23 -0
- package/dist/schema-compiler.mjs +265 -0
- package/dist/schema-validator.d.mts +15 -0
- package/dist/schema-validator.mjs +446 -0
- package/dist/schemas/draft-04-schema.mjs +125 -0
- package/dist/schemas/draft-06-schema.mjs +126 -0
- package/dist/schemas/draft-07-schema.mjs +141 -0
- package/dist/schemas/draft-2019-09-meta-applicator.mjs +46 -0
- package/dist/schemas/draft-2019-09-meta-content.mjs +15 -0
- package/dist/schemas/draft-2019-09-meta-core.mjs +52 -0
- package/dist/schemas/draft-2019-09-meta-format.mjs +11 -0
- package/dist/schemas/draft-2019-09-meta-meta-data.mjs +31 -0
- package/dist/schemas/draft-2019-09-meta-validation.mjs +80 -0
- package/dist/schemas/draft-2019-09-schema.mjs +39 -0
- package/dist/schemas/draft-2020-12-meta-applicator.mjs +45 -0
- package/dist/schemas/draft-2020-12-meta-content.mjs +15 -0
- package/dist/schemas/draft-2020-12-meta-core.mjs +46 -0
- package/dist/schemas/draft-2020-12-meta-format-annotation.mjs +11 -0
- package/dist/schemas/draft-2020-12-meta-format-assertion.mjs +11 -0
- package/dist/schemas/draft-2020-12-meta-meta-data.mjs +31 -0
- package/dist/schemas/draft-2020-12-meta-unevaluated.mjs +14 -0
- package/dist/schemas/draft-2020-12-meta-validation.mjs +80 -0
- package/dist/schemas/draft-2020-12-schema.mjs +55 -0
- package/dist/utils/array.mjs +54 -0
- package/dist/utils/base64.mjs +21 -0
- package/dist/utils/clone.mjs +42 -0
- package/dist/utils/constants.mjs +16 -0
- package/dist/utils/date.mjs +19 -0
- package/dist/utils/hostname.mjs +73 -0
- package/dist/utils/json.mjs +34 -0
- package/dist/utils/properties.mjs +11 -0
- package/dist/utils/schema-regex.mjs +49 -0
- package/dist/utils/symbols.mjs +5 -0
- package/dist/utils/time.mjs +42 -0
- package/dist/utils/unicode.mjs +12 -0
- package/dist/utils/uri.mjs +12 -0
- package/dist/utils/what-is.mjs +23 -0
- package/dist/validation/array.mjs +57 -0
- package/dist/validation/combinators.mjs +62 -0
- package/dist/validation/numeric.mjs +38 -0
- package/dist/validation/object.mjs +109 -0
- package/dist/validation/ref.mjs +49 -0
- package/dist/validation/shared.mjs +97 -0
- package/dist/validation/string.mjs +88 -0
- package/dist/validation/type.mjs +32 -0
- package/dist/z-schema-base.d.mts +85 -0
- package/dist/z-schema-base.mjs +230 -0
- package/dist/z-schema-options.d.mts +35 -0
- package/dist/z-schema-options.mjs +55 -0
- package/dist/z-schema-reader.d.mts +6 -0
- package/dist/z-schema-reader.mjs +10 -0
- package/dist/z-schema-versions.mjs +67 -0
- package/dist/z-schema.d.mts +193 -0
- package/dist/z-schema.mjs +300 -0
- package/package.json +49 -64
- package/src/index.ts +3 -3
- package/src/schema-compiler.ts +30 -10
- package/src/schema-validator.ts +1 -1
- package/src/utils/schema-regex.ts +13 -2
- package/src/z-schema-base.ts +1 -1
- package/src/z-schema-versions.ts +1 -2
- package/src/z-schema.ts +0 -1
- package/umd/ZSchema.js +5934 -8110
- package/umd/ZSchema.min.js +2 -1
- package/dist/errors.js +0 -72
- package/dist/format-validators.js +0 -392
- package/dist/index.js +0 -5
- package/dist/json-schema-versions.js +0 -8
- package/dist/json-schema.js +0 -84
- package/dist/json-validation.js +0 -728
- package/dist/package.json +0 -3
- package/dist/report.js +0 -265
- package/dist/schema-cache.js +0 -211
- package/dist/schema-compiler.js +0 -415
- package/dist/schema-validator.js +0 -721
- package/dist/schemas/draft-04-schema.json +0 -149
- package/dist/schemas/draft-06-schema.json +0 -155
- package/dist/schemas/draft-07-schema.json +0 -172
- package/dist/schemas/draft-2019-09-meta-applicator.json +0 -52
- package/dist/schemas/draft-2019-09-meta-content.json +0 -12
- package/dist/schemas/draft-2019-09-meta-core.json +0 -53
- package/dist/schemas/draft-2019-09-meta-format.json +0 -10
- package/dist/schemas/draft-2019-09-meta-meta-data.json +0 -32
- package/dist/schemas/draft-2019-09-meta-validation.json +0 -94
- package/dist/schemas/draft-2019-09-schema.json +0 -41
- package/dist/schemas/draft-2020-12-meta-applicator.json +0 -44
- package/dist/schemas/draft-2020-12-meta-content.json +0 -12
- package/dist/schemas/draft-2020-12-meta-core.json +0 -47
- package/dist/schemas/draft-2020-12-meta-format-annotation.json +0 -10
- package/dist/schemas/draft-2020-12-meta-format-assertion.json +0 -10
- package/dist/schemas/draft-2020-12-meta-meta-data.json +0 -32
- package/dist/schemas/draft-2020-12-meta-unevaluated.json +0 -11
- package/dist/schemas/draft-2020-12-meta-validation.json +0 -94
- package/dist/schemas/draft-2020-12-schema.json +0 -57
- package/dist/types/errors.d.ts +0 -64
- package/dist/types/format-validators.d.ts +0 -11
- package/dist/types/index.d.ts +0 -14
- package/dist/types/json-schema-versions.d.ts +0 -142
- package/dist/types/json-schema.d.ts +0 -66
- package/dist/types/json-validation.d.ts +0 -6
- package/dist/types/report.d.ts +0 -94
- package/dist/types/schema-cache.d.ts +0 -27
- package/dist/types/schema-compiler.d.ts +0 -31
- package/dist/types/schema-validator.d.ts +0 -10
- package/dist/types/utils/array.d.ts +0 -9
- package/dist/types/utils/base64.d.ts +0 -2
- package/dist/types/utils/clone.d.ts +0 -2
- package/dist/types/utils/constants.d.ts +0 -19
- package/dist/types/utils/date.d.ts +0 -1
- package/dist/types/utils/hostname.d.ts +0 -2
- package/dist/types/utils/json.d.ts +0 -9
- package/dist/types/utils/properties.d.ts +0 -1
- package/dist/types/utils/schema-regex.d.ts +0 -10
- package/dist/types/utils/symbols.d.ts +0 -2
- package/dist/types/utils/time.d.ts +0 -12
- package/dist/types/utils/unicode.d.ts +0 -5
- package/dist/types/utils/uri.d.ts +0 -4
- package/dist/types/utils/what-is.d.ts +0 -4
- package/dist/types/validation/array.d.ts +0 -12
- package/dist/types/validation/combinators.d.ts +0 -10
- package/dist/types/validation/numeric.d.ts +0 -8
- package/dist/types/validation/object.d.ts +0 -13
- package/dist/types/validation/ref.d.ts +0 -11
- package/dist/types/validation/shared.d.ts +0 -26
- package/dist/types/validation/string.d.ts +0 -9
- package/dist/types/validation/type.d.ts +0 -6
- package/dist/types/z-schema-base.d.ts +0 -87
- package/dist/types/z-schema-options.d.ts +0 -35
- package/dist/types/z-schema-reader.d.ts +0 -4
- package/dist/types/z-schema-versions.d.ts +0 -1
- package/dist/types/z-schema.d.ts +0 -191
- package/dist/utils/array.js +0 -69
- package/dist/utils/base64.js +0 -29
- package/dist/utils/clone.js +0 -59
- package/dist/utils/constants.js +0 -19
- package/dist/utils/date.js +0 -21
- package/dist/utils/hostname.js +0 -146
- package/dist/utils/json.js +0 -70
- package/dist/utils/properties.js +0 -10
- package/dist/utils/schema-regex.js +0 -52
- package/dist/utils/symbols.js +0 -2
- package/dist/utils/time.js +0 -50
- package/dist/utils/unicode.js +0 -12
- package/dist/utils/uri.js +0 -15
- package/dist/utils/what-is.js +0 -32
- package/dist/validation/array.js +0 -127
- package/dist/validation/combinators.js +0 -106
- package/dist/validation/numeric.js +0 -97
- package/dist/validation/object.js +0 -237
- package/dist/validation/ref.js +0 -70
- package/dist/validation/shared.js +0 -136
- package/dist/validation/string.js +0 -170
- package/dist/validation/type.js +0 -55
- package/dist/z-schema-base.js +0 -286
- package/dist/z-schema-options.js +0 -99
- package/dist/z-schema-reader.js +0 -7
- package/dist/z-schema-versions.js +0 -110
- package/dist/z-schema.js +0 -287
package/dist/json-validation.js
DELETED
|
@@ -1,728 +0,0 @@
|
|
|
1
|
-
import { getId } from './json-schema.js';
|
|
2
|
-
import { Report } from './report.js';
|
|
3
|
-
import { compileSchemaRegex } from './utils/schema-regex.js';
|
|
4
|
-
import { isObject, whatIs } from './utils/what-is.js';
|
|
5
|
-
import { additionalItemsValidator, containsValidator, itemsValidator, maxContainsValidator, maxItemsValidator, minContainsValidator, minItemsValidator, prefixItemsValidator, uniqueItemsValidator, } from './validation/array.js';
|
|
6
|
-
import { allOfValidator, anyOfValidator, elseValidator, ifValidator, notValidator, oneOfValidator, thenValidator, } from './validation/combinators.js';
|
|
7
|
-
import { exclusiveMaximumValidator, exclusiveMinimumValidator, maximumValidator, minimumValidator, multipleOfValidator, } from './validation/numeric.js';
|
|
8
|
-
import { additionalPropertiesValidator, dependenciesValidator, dependentRequiredValidator, dependentSchemasValidator, maxPropertiesValidator, minPropertiesValidator, patternPropertiesValidator, propertiesValidator, propertyNamesValidator, requiredValidator, } from './validation/object.js';
|
|
9
|
-
import { resolveDynamicRef, resolveRecursiveRef } from './validation/ref.js';
|
|
10
|
-
import { getCachedValidationResult, isValidationVocabularyEnabled, VALIDATION_VOCAB_KEYWORDS, } from './validation/shared.js';
|
|
11
|
-
import { contentEncodingValidator, contentMediaTypeValidator, formatValidator, maxLengthValidator, minLengthValidator, patternValidator, } from './validation/string.js';
|
|
12
|
-
import { constValidator, enumValidator, typeValidator } from './validation/type.js';
|
|
13
|
-
function collectEvaluated(args) {
|
|
14
|
-
const { report, currentSchema, json, mode, depth } = args;
|
|
15
|
-
if (!currentSchema || typeof currentSchema === 'boolean') {
|
|
16
|
-
return new Set();
|
|
17
|
-
}
|
|
18
|
-
if (depth > (this.options.maxRecursionDepth ?? 100)) {
|
|
19
|
-
report.addError('COLLECT_EVALUATED_DEPTH_EXCEEDED', [depth]);
|
|
20
|
-
return new Set();
|
|
21
|
-
}
|
|
22
|
-
const evaluated = new Set();
|
|
23
|
-
const merge = (other) => {
|
|
24
|
-
if (other === 'all')
|
|
25
|
-
return true;
|
|
26
|
-
for (const v of other) {
|
|
27
|
-
evaluated.add(v);
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
};
|
|
31
|
-
const recurse = (subSchema) => {
|
|
32
|
-
if (mode === 'items') {
|
|
33
|
-
return collectEvaluated.call(this, {
|
|
34
|
-
report,
|
|
35
|
-
currentSchema: subSchema,
|
|
36
|
-
json,
|
|
37
|
-
mode: 'items',
|
|
38
|
-
jsonArr: args.jsonArr,
|
|
39
|
-
depth: depth + 1,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return collectEvaluated.call(this, {
|
|
43
|
-
report,
|
|
44
|
-
currentSchema: subSchema,
|
|
45
|
-
json,
|
|
46
|
-
mode: 'properties',
|
|
47
|
-
jsonData: args.jsonData,
|
|
48
|
-
depth: depth + 1,
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
// --- Mode-specific leaf collection ---
|
|
52
|
-
if (mode === 'items') {
|
|
53
|
-
const jsonArr = args.jsonArr;
|
|
54
|
-
// prefixItems (2020-12 tuple)
|
|
55
|
-
if (Array.isArray(currentSchema.prefixItems)) {
|
|
56
|
-
const len = Math.min(currentSchema.prefixItems.length, jsonArr.length);
|
|
57
|
-
for (let i = 0; i < len; i++) {
|
|
58
|
-
evaluated.add(i);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// items - can be array (2019-09 tuple) or schema (evaluates all)
|
|
62
|
-
if (currentSchema.items !== undefined) {
|
|
63
|
-
if (Array.isArray(currentSchema.items)) {
|
|
64
|
-
const len = Math.min(currentSchema.items.length, jsonArr.length);
|
|
65
|
-
for (let i = 0; i < len; i++) {
|
|
66
|
-
evaluated.add(i);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else if (currentSchema.items !== false) {
|
|
70
|
-
return 'all';
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// additionalItems (2019-09) - when items is array form and additionalItems is present and not false
|
|
74
|
-
if (currentSchema.additionalItems !== undefined &&
|
|
75
|
-
currentSchema.additionalItems !== false &&
|
|
76
|
-
Array.isArray(currentSchema.items)) {
|
|
77
|
-
return 'all';
|
|
78
|
-
}
|
|
79
|
-
// contains - evaluates specific indices that match the schema
|
|
80
|
-
if (currentSchema.contains !== undefined) {
|
|
81
|
-
for (let i = 0; i < jsonArr.length; i++) {
|
|
82
|
-
let passed = getCachedValidationResult(report, currentSchema.contains, jsonArr[i]);
|
|
83
|
-
if (passed === undefined) {
|
|
84
|
-
const subReport = new Report(report);
|
|
85
|
-
validate.call(this, subReport, currentSchema.contains, jsonArr[i]);
|
|
86
|
-
passed = subReport.errors.length === 0;
|
|
87
|
-
}
|
|
88
|
-
if (passed) {
|
|
89
|
-
evaluated.add(i);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// unevaluatedItems: true means all items evaluated
|
|
94
|
-
if (currentSchema.unevaluatedItems === true) {
|
|
95
|
-
return 'all';
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
// mode === 'properties'
|
|
100
|
-
const jsonData = args.jsonData;
|
|
101
|
-
// properties
|
|
102
|
-
if (isObject(currentSchema.properties)) {
|
|
103
|
-
for (const key of Object.keys(currentSchema.properties)) {
|
|
104
|
-
if (Object.hasOwn(jsonData, key)) {
|
|
105
|
-
evaluated.add(key);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// patternProperties
|
|
110
|
-
if (isObject(currentSchema.patternProperties)) {
|
|
111
|
-
for (const pattern of Object.keys(currentSchema.patternProperties)) {
|
|
112
|
-
const result = compileSchemaRegex(pattern);
|
|
113
|
-
if (result.ok) {
|
|
114
|
-
for (const key of Object.keys(jsonData)) {
|
|
115
|
-
if (result.value.test(key)) {
|
|
116
|
-
evaluated.add(key);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// additionalProperties - evaluates all non-properties/non-patternProperties keys
|
|
123
|
-
if (currentSchema.additionalProperties !== undefined) {
|
|
124
|
-
const propKeys = isObject(currentSchema.properties) ? Object.keys(currentSchema.properties) : [];
|
|
125
|
-
const patternRegexes = [];
|
|
126
|
-
if (isObject(currentSchema.patternProperties)) {
|
|
127
|
-
for (const pattern of Object.keys(currentSchema.patternProperties)) {
|
|
128
|
-
const result = compileSchemaRegex(pattern);
|
|
129
|
-
if (result.ok) {
|
|
130
|
-
patternRegexes.push(result.value);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
for (const key of Object.keys(jsonData)) {
|
|
135
|
-
if (propKeys.includes(key))
|
|
136
|
-
continue;
|
|
137
|
-
if (patternRegexes.some((re) => re.test(key)))
|
|
138
|
-
continue;
|
|
139
|
-
evaluated.add(key);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// dependentSchemas - only applies when the dependency key is present in the data
|
|
143
|
-
if (isObject(currentSchema.dependentSchemas)) {
|
|
144
|
-
for (const [depKey, depSchema] of Object.entries(currentSchema.dependentSchemas)) {
|
|
145
|
-
if (Object.hasOwn(jsonData, depKey)) {
|
|
146
|
-
if (merge(recurse(depSchema))) {
|
|
147
|
-
return 'all';
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// unevaluatedProperties: true in a sub-schema means all props are evaluated
|
|
153
|
-
if (currentSchema.unevaluatedProperties === true) {
|
|
154
|
-
return 'all';
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// --- Shared combinator traversal ---
|
|
158
|
-
// allOf
|
|
159
|
-
if (Array.isArray(currentSchema.allOf)) {
|
|
160
|
-
for (const subSchema of currentSchema.allOf) {
|
|
161
|
-
if (merge(recurse(subSchema))) {
|
|
162
|
-
return 'all';
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// anyOf - only matching branches contribute
|
|
167
|
-
if (Array.isArray(currentSchema.anyOf)) {
|
|
168
|
-
for (const subSchema of currentSchema.anyOf) {
|
|
169
|
-
let passed = getCachedValidationResult(report, subSchema, json);
|
|
170
|
-
if (passed === undefined) {
|
|
171
|
-
const subReport = new Report(report);
|
|
172
|
-
validate.call(this, subReport, subSchema, json);
|
|
173
|
-
passed = subReport.errors.length === 0;
|
|
174
|
-
}
|
|
175
|
-
if (passed) {
|
|
176
|
-
if (merge(recurse(subSchema))) {
|
|
177
|
-
return 'all';
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// oneOf - only matching branches contribute
|
|
183
|
-
if (Array.isArray(currentSchema.oneOf)) {
|
|
184
|
-
for (const subSchema of currentSchema.oneOf) {
|
|
185
|
-
let passed = getCachedValidationResult(report, subSchema, json);
|
|
186
|
-
if (passed === undefined) {
|
|
187
|
-
const subReport = new Report(report);
|
|
188
|
-
validate.call(this, subReport, subSchema, json);
|
|
189
|
-
passed = subReport.errors.length === 0;
|
|
190
|
-
}
|
|
191
|
-
if (passed) {
|
|
192
|
-
if (merge(recurse(subSchema))) {
|
|
193
|
-
return 'all';
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// if/then/else
|
|
199
|
-
if (currentSchema.if !== undefined) {
|
|
200
|
-
let condPassed = getCachedValidationResult(report, currentSchema.if, json);
|
|
201
|
-
if (condPassed === undefined) {
|
|
202
|
-
const condReport = new Report(report);
|
|
203
|
-
validate.call(this, condReport, currentSchema.if, json);
|
|
204
|
-
condPassed = condReport.errors.length === 0;
|
|
205
|
-
}
|
|
206
|
-
if (condPassed) {
|
|
207
|
-
if (merge(recurse(currentSchema.if))) {
|
|
208
|
-
return 'all';
|
|
209
|
-
}
|
|
210
|
-
if (currentSchema.then !== undefined) {
|
|
211
|
-
if (merge(recurse(currentSchema.then))) {
|
|
212
|
-
return 'all';
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
if (currentSchema.else !== undefined) {
|
|
218
|
-
if (merge(recurse(currentSchema.else))) {
|
|
219
|
-
return 'all';
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
// $ref resolved
|
|
225
|
-
if (currentSchema.__$refResolved && currentSchema.__$refResolved !== currentSchema) {
|
|
226
|
-
if (merge(recurse(currentSchema.__$refResolved))) {
|
|
227
|
-
return 'all';
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// $recursiveRef
|
|
231
|
-
const recursiveTarget = resolveRecursiveRef(currentSchema, report.__$recursiveAnchorStack);
|
|
232
|
-
if (recursiveTarget && recursiveTarget !== currentSchema) {
|
|
233
|
-
if (merge(recurse(recursiveTarget))) {
|
|
234
|
-
return 'all';
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
// $dynamicRef
|
|
238
|
-
const dynamicTarget = resolveDynamicRef(currentSchema, report.__$dynamicScopeStack);
|
|
239
|
-
if (dynamicTarget && dynamicTarget !== currentSchema) {
|
|
240
|
-
if (merge(recurse(dynamicTarget))) {
|
|
241
|
-
return 'all';
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return evaluated;
|
|
245
|
-
}
|
|
246
|
-
// ---------------------------------------------------------------------------
|
|
247
|
-
// unevaluatedItems
|
|
248
|
-
// ---------------------------------------------------------------------------
|
|
249
|
-
function unevaluatedItemsValidator(report, schema, json) {
|
|
250
|
-
if (!Array.isArray(json)) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
// unevaluatedItems: true means all items are valid
|
|
254
|
-
if (schema.unevaluatedItems === true) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
const unevalSchema = schema.unevaluatedItems;
|
|
258
|
-
if (unevalSchema === undefined) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
if (json.length === 0) {
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
const evaluatedItems = collectEvaluated.call(this, {
|
|
265
|
-
report,
|
|
266
|
-
currentSchema: schema,
|
|
267
|
-
json,
|
|
268
|
-
mode: 'items',
|
|
269
|
-
jsonArr: json,
|
|
270
|
-
depth: 0,
|
|
271
|
-
});
|
|
272
|
-
if (evaluatedItems === 'all') {
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
const unevaluatedIndices = [];
|
|
276
|
-
for (let i = 0; i < json.length; i++) {
|
|
277
|
-
if (!evaluatedItems.has(i)) {
|
|
278
|
-
unevaluatedIndices.push(i);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (unevaluatedIndices.length === 0) {
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
if (unevalSchema === false) {
|
|
285
|
-
report.addError('ARRAY_UNEVALUATED_ITEMS', undefined, undefined, schema, 'unevaluatedItems');
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
// unevaluatedItems as a schema — validate each unevaluated item against it
|
|
289
|
-
for (const idx of unevaluatedIndices) {
|
|
290
|
-
const subReport = new Report(report);
|
|
291
|
-
validate.call(this, subReport, unevalSchema, json[idx]);
|
|
292
|
-
if (subReport.errors.length > 0) {
|
|
293
|
-
report.addError('ARRAY_UNEVALUATED_ITEMS', undefined, undefined, schema, 'unevaluatedItems');
|
|
294
|
-
break;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// ---------------------------------------------------------------------------
|
|
300
|
-
// unevaluatedProperties
|
|
301
|
-
// ---------------------------------------------------------------------------
|
|
302
|
-
function unevaluatedPropertiesValidator(report, schema, json) {
|
|
303
|
-
if (!isObject(json)) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
// unevaluatedProperties: true means all properties are valid
|
|
307
|
-
if (schema.unevaluatedProperties === true) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
// unevaluatedProperties: false or unevaluatedProperties: {schema} both need evaluation
|
|
311
|
-
const unevalSchema = schema.unevaluatedProperties;
|
|
312
|
-
if (unevalSchema === undefined) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const allKeys = Object.keys(json);
|
|
316
|
-
if (allKeys.length === 0) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
const evaluatedProperties = collectEvaluated.call(this, {
|
|
320
|
-
report,
|
|
321
|
-
currentSchema: schema,
|
|
322
|
-
json,
|
|
323
|
-
mode: 'properties',
|
|
324
|
-
jsonData: json,
|
|
325
|
-
depth: 0,
|
|
326
|
-
});
|
|
327
|
-
if (evaluatedProperties === 'all') {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
const unevaluatedKeys = allKeys.filter((key) => !evaluatedProperties.has(key));
|
|
331
|
-
if (unevaluatedKeys.length === 0) {
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
if (unevalSchema === false) {
|
|
335
|
-
report.addError('OBJECT_UNEVALUATED_PROPERTIES', [unevaluatedKeys.join(', ')], undefined, schema, 'unevaluatedProperties');
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
// unevaluatedProperties as a schema — validate each unevaluated key against it
|
|
339
|
-
for (const key of unevaluatedKeys) {
|
|
340
|
-
const subReport = new Report(report);
|
|
341
|
-
validate.call(this, subReport, unevalSchema, json[key]);
|
|
342
|
-
if (subReport.errors.length > 0) {
|
|
343
|
-
report.addError('OBJECT_UNEVALUATED_PROPERTIES', [key], undefined, schema, 'unevaluatedProperties');
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
// ---------------------------------------------------------------------------
|
|
349
|
-
// definitions (no-op)
|
|
350
|
-
// ---------------------------------------------------------------------------
|
|
351
|
-
function definitionsValidator() {
|
|
352
|
-
/*report: Report, schema: JsonSchemaInternal, json: unknown*/
|
|
353
|
-
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.2
|
|
354
|
-
// nothing to do here
|
|
355
|
-
}
|
|
356
|
-
// ---------------------------------------------------------------------------
|
|
357
|
-
// JsonValidators — keyword dispatch table
|
|
358
|
-
// ---------------------------------------------------------------------------
|
|
359
|
-
export const JsonValidators = {
|
|
360
|
-
// no-op validators (metadata / handled elsewhere)
|
|
361
|
-
id: () => { },
|
|
362
|
-
$id: () => { },
|
|
363
|
-
$ref: () => { },
|
|
364
|
-
$schema: () => { },
|
|
365
|
-
$dynamicAnchor: () => { },
|
|
366
|
-
$dynamicRef: () => { },
|
|
367
|
-
$anchor: () => { },
|
|
368
|
-
$defs: () => { },
|
|
369
|
-
$vocabulary: () => { },
|
|
370
|
-
$recursiveAnchor: () => { },
|
|
371
|
-
$recursiveRef: () => { },
|
|
372
|
-
examples: () => { },
|
|
373
|
-
title: () => { },
|
|
374
|
-
description: () => { },
|
|
375
|
-
default: () => { },
|
|
376
|
-
// type validators
|
|
377
|
-
type: typeValidator,
|
|
378
|
-
enum: enumValidator,
|
|
379
|
-
const: constValidator,
|
|
380
|
-
// numeric validators
|
|
381
|
-
multipleOf: multipleOfValidator,
|
|
382
|
-
maximum: maximumValidator,
|
|
383
|
-
exclusiveMaximum: exclusiveMaximumValidator,
|
|
384
|
-
minimum: minimumValidator,
|
|
385
|
-
exclusiveMinimum: exclusiveMinimumValidator,
|
|
386
|
-
// string validators
|
|
387
|
-
maxLength: maxLengthValidator,
|
|
388
|
-
minLength: minLengthValidator,
|
|
389
|
-
pattern: patternValidator,
|
|
390
|
-
format: formatValidator,
|
|
391
|
-
contentEncoding: contentEncodingValidator,
|
|
392
|
-
contentMediaType: contentMediaTypeValidator,
|
|
393
|
-
// array validators
|
|
394
|
-
additionalItems: additionalItemsValidator,
|
|
395
|
-
items: itemsValidator,
|
|
396
|
-
prefixItems: prefixItemsValidator,
|
|
397
|
-
maxItems: maxItemsValidator,
|
|
398
|
-
minItems: minItemsValidator,
|
|
399
|
-
uniqueItems: uniqueItemsValidator,
|
|
400
|
-
contains: containsValidator,
|
|
401
|
-
maxContains: maxContainsValidator,
|
|
402
|
-
minContains: minContainsValidator,
|
|
403
|
-
unevaluatedItems: unevaluatedItemsValidator,
|
|
404
|
-
// object validators
|
|
405
|
-
maxProperties: maxPropertiesValidator,
|
|
406
|
-
minProperties: minPropertiesValidator,
|
|
407
|
-
required: requiredValidator,
|
|
408
|
-
additionalProperties: additionalPropertiesValidator,
|
|
409
|
-
patternProperties: patternPropertiesValidator,
|
|
410
|
-
properties: propertiesValidator,
|
|
411
|
-
dependencies: dependenciesValidator,
|
|
412
|
-
dependentSchemas: dependentSchemasValidator,
|
|
413
|
-
dependentRequired: dependentRequiredValidator,
|
|
414
|
-
propertyNames: propertyNamesValidator,
|
|
415
|
-
unevaluatedProperties: unevaluatedPropertiesValidator,
|
|
416
|
-
// combinator validators
|
|
417
|
-
allOf: allOfValidator,
|
|
418
|
-
anyOf: anyOfValidator,
|
|
419
|
-
oneOf: oneOfValidator,
|
|
420
|
-
not: notValidator,
|
|
421
|
-
if: ifValidator,
|
|
422
|
-
then: thenValidator,
|
|
423
|
-
else: elseValidator,
|
|
424
|
-
// misc
|
|
425
|
-
definitions: definitionsValidator,
|
|
426
|
-
};
|
|
427
|
-
// ---------------------------------------------------------------------------
|
|
428
|
-
// recurseArray
|
|
429
|
-
// ---------------------------------------------------------------------------
|
|
430
|
-
const recurseArray = function (report, schema, json) {
|
|
431
|
-
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.2
|
|
432
|
-
const schemaUri = typeof schema.$schema === 'string' ? schema.$schema : undefined;
|
|
433
|
-
const isDraft202012Schema = schemaUri === 'https://json-schema.org/draft/2020-12/schema' ||
|
|
434
|
-
(!schemaUri && this.options.version === 'draft2020-12');
|
|
435
|
-
const prefixItems = isDraft202012Schema && Array.isArray(schema.prefixItems) ? schema.prefixItems : undefined;
|
|
436
|
-
if (prefixItems) {
|
|
437
|
-
for (let idx = 0; idx < json.length; idx++) {
|
|
438
|
-
if (idx < prefixItems.length) {
|
|
439
|
-
report.path.push(idx);
|
|
440
|
-
validate.call(this, report, prefixItems[idx], json[idx]);
|
|
441
|
-
report.path.pop();
|
|
442
|
-
}
|
|
443
|
-
else if (schema.items !== undefined && !Array.isArray(schema.items)) {
|
|
444
|
-
report.path.push(idx);
|
|
445
|
-
report.schemaPath.push('items');
|
|
446
|
-
validate.call(this, report, schema.items, json[idx]);
|
|
447
|
-
report.schemaPath.pop();
|
|
448
|
-
report.path.pop();
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
// If "items" is an array, this situation, the schema depends on the index:
|
|
454
|
-
// if the index is less than, or equal to, the size of "items",
|
|
455
|
-
// the child instance must be valid against the corresponding schema in the "items" array;
|
|
456
|
-
// otherwise, it must be valid against the schema defined by "additionalItems".
|
|
457
|
-
if (Array.isArray(schema.items)) {
|
|
458
|
-
for (let idx = 0; idx < json.length; idx++) {
|
|
459
|
-
// equal to doesn't make sense here
|
|
460
|
-
if (idx < schema.items.length) {
|
|
461
|
-
report.path.push(idx);
|
|
462
|
-
validate.call(this, report, schema.items[idx], json[idx]);
|
|
463
|
-
report.path.pop();
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
// might be boolean, so check that it's an object
|
|
467
|
-
if (typeof schema.additionalItems === 'object') {
|
|
468
|
-
report.path.push(idx);
|
|
469
|
-
validate.call(this, report, schema.additionalItems, json[idx]);
|
|
470
|
-
report.path.pop();
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else if (typeof schema.items === 'object' || typeof schema.items === 'boolean') {
|
|
476
|
-
// If items is a schema, then the child instance must be valid against this schema,
|
|
477
|
-
// regardless of its index, and regardless of the value of "additionalItems".
|
|
478
|
-
for (let idx = 0; idx < json.length; idx++) {
|
|
479
|
-
report.path.push(idx);
|
|
480
|
-
// Track schema path for array items validation
|
|
481
|
-
report.schemaPath.push('items');
|
|
482
|
-
validate.call(this, report, schema.items, json[idx]);
|
|
483
|
-
report.schemaPath.pop();
|
|
484
|
-
report.path.pop();
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
};
|
|
488
|
-
// ---------------------------------------------------------------------------
|
|
489
|
-
// recurseObject
|
|
490
|
-
// ---------------------------------------------------------------------------
|
|
491
|
-
const recurseObject = function (report, schema, json) {
|
|
492
|
-
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.3
|
|
493
|
-
// If "additionalProperties" is absent, it is considered present with an empty schema as a value.
|
|
494
|
-
// In addition, boolean value true is considered equivalent to an empty schema.
|
|
495
|
-
let additionalProperties = schema.additionalProperties;
|
|
496
|
-
if (additionalProperties === true || additionalProperties === undefined) {
|
|
497
|
-
additionalProperties = {};
|
|
498
|
-
}
|
|
499
|
-
// p - The property set from "properties".
|
|
500
|
-
const p = schema.properties ? Object.keys(schema.properties) : [];
|
|
501
|
-
// pp - The property set from "patternProperties". Elements of this set will be called regexes for convenience.
|
|
502
|
-
const pp = schema.patternProperties ? Object.keys(schema.patternProperties) : [];
|
|
503
|
-
// m - The property name of the child.
|
|
504
|
-
const keys = Object.keys(json);
|
|
505
|
-
for (const m of keys) {
|
|
506
|
-
const propertyValue = json[m];
|
|
507
|
-
// s - The set of schemas for the child instance.
|
|
508
|
-
const s = [];
|
|
509
|
-
// 1. If set "p" contains value "m", then the corresponding schema in "properties" is added to "s".
|
|
510
|
-
if (p.includes(m)) {
|
|
511
|
-
s.push(schema.properties[m]);
|
|
512
|
-
}
|
|
513
|
-
// 2. For each regex in "pp", if it matches "m" successfully, the corresponding schema in "patternProperties" is added to "s".
|
|
514
|
-
for (const regexString of pp) {
|
|
515
|
-
const result = compileSchemaRegex(regexString);
|
|
516
|
-
if (result.ok && result.value.test(m) === true) {
|
|
517
|
-
s.push(schema.patternProperties[regexString]);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
// 3. The schema defined by "additionalProperties" is added to "s" if and only if, at this stage, "s" is empty.
|
|
521
|
-
if (s.length === 0 && additionalProperties !== false) {
|
|
522
|
-
s.push(additionalProperties);
|
|
523
|
-
}
|
|
524
|
-
// we are passing tests even without this assert because this is covered by properties check
|
|
525
|
-
// if s is empty in this stage, no additionalProperties are allowed
|
|
526
|
-
// report.expect(s.length !== 0, 'E001', m);
|
|
527
|
-
// Instance property value must pass all schemas from s
|
|
528
|
-
for (const schema_s of s) {
|
|
529
|
-
report.path.push(m);
|
|
530
|
-
// Track schema path for properties validation
|
|
531
|
-
if (p.includes(m)) {
|
|
532
|
-
// This is a defined property
|
|
533
|
-
report.schemaPath.push('properties');
|
|
534
|
-
report.schemaPath.push(m);
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
// This is additionalProperties or patternProperties
|
|
538
|
-
report.schemaPath.push('additionalProperties');
|
|
539
|
-
}
|
|
540
|
-
validate.call(this, report, schema_s, propertyValue);
|
|
541
|
-
report.path.pop();
|
|
542
|
-
report.schemaPath.pop();
|
|
543
|
-
if (p.includes(m)) {
|
|
544
|
-
report.schemaPath.pop(); // pop the property name for defined properties
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
// ---------------------------------------------------------------------------
|
|
550
|
-
// validate — main entry point
|
|
551
|
-
// ---------------------------------------------------------------------------
|
|
552
|
-
export function validate(report, schema, json) {
|
|
553
|
-
report.commonErrorMessage = 'JSON_OBJECT_VALIDATION_FAILED';
|
|
554
|
-
if (schema === true) {
|
|
555
|
-
return true;
|
|
556
|
-
}
|
|
557
|
-
if (schema === false) {
|
|
558
|
-
report.addError('SCHEMA_IS_FALSE', [], undefined, schema);
|
|
559
|
-
return false;
|
|
560
|
-
}
|
|
561
|
-
// check if schema is an object
|
|
562
|
-
if (!isObject(schema)) {
|
|
563
|
-
report.addError('SCHEMA_NOT_AN_OBJECT', [whatIs(schema)], undefined, schema);
|
|
564
|
-
return false;
|
|
565
|
-
}
|
|
566
|
-
// check if schema is empty, everything is valid against empty schema
|
|
567
|
-
let keys = Object.keys(schema);
|
|
568
|
-
if (keys.length === 0) {
|
|
569
|
-
return true;
|
|
570
|
-
}
|
|
571
|
-
// this method can be called recursively, so we need to remember our root
|
|
572
|
-
let isRoot = false;
|
|
573
|
-
if (!report.rootSchema) {
|
|
574
|
-
report.rootSchema = schema;
|
|
575
|
-
isRoot = true;
|
|
576
|
-
}
|
|
577
|
-
const recursiveAnchorStack = report.__$recursiveAnchorStack;
|
|
578
|
-
const dynamicScopeStack = report.__$dynamicScopeStack;
|
|
579
|
-
let pushedRecursiveAnchor = false;
|
|
580
|
-
let pushedDynamicScope = false;
|
|
581
|
-
const schemaId = getId(schema);
|
|
582
|
-
const schemaResourceRoot = schema.__$resourceRoot;
|
|
583
|
-
const dynamicScopeEntry = schemaResourceRoot || (isRoot || typeof schemaId === 'string' ? schema : undefined);
|
|
584
|
-
if (dynamicScopeEntry && dynamicScopeStack[dynamicScopeStack.length - 1] !== dynamicScopeEntry) {
|
|
585
|
-
dynamicScopeStack.push(dynamicScopeEntry);
|
|
586
|
-
pushedDynamicScope = true;
|
|
587
|
-
}
|
|
588
|
-
if (schema.$recursiveAnchor === true) {
|
|
589
|
-
recursiveAnchorStack.push(schema);
|
|
590
|
-
pushedRecursiveAnchor = true;
|
|
591
|
-
}
|
|
592
|
-
// follow schema.$ref keys
|
|
593
|
-
if (schema.$ref !== undefined) {
|
|
594
|
-
const applySiblingKeywordsWithRef = this.options.version === 'draft2019-09' || this.options.version === 'draft2020-12';
|
|
595
|
-
if (applySiblingKeywordsWithRef) {
|
|
596
|
-
if (!schema.__$refResolved) {
|
|
597
|
-
report.addError('REF_UNRESOLVED', [schema.$ref], undefined, schema);
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
validate.call(this, report, schema.__$refResolved, json);
|
|
601
|
-
}
|
|
602
|
-
keys = keys.filter((key) => key !== '$ref');
|
|
603
|
-
}
|
|
604
|
-
else {
|
|
605
|
-
// avoid infinite loop with maxRefs
|
|
606
|
-
let maxRefs = 99;
|
|
607
|
-
while (schema.$ref && maxRefs > 0) {
|
|
608
|
-
if (!schema.__$refResolved) {
|
|
609
|
-
report.addError('REF_UNRESOLVED', [schema.$ref], undefined, schema);
|
|
610
|
-
break;
|
|
611
|
-
}
|
|
612
|
-
else if (schema.__$refResolved === schema) {
|
|
613
|
-
break;
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
schema = schema.__$refResolved;
|
|
617
|
-
keys = Object.keys(schema);
|
|
618
|
-
}
|
|
619
|
-
maxRefs--;
|
|
620
|
-
}
|
|
621
|
-
if (maxRefs === 0) {
|
|
622
|
-
throw new Error('Circular dependency by $ref references!');
|
|
623
|
-
}
|
|
624
|
-
// Reset schema path for referenced schema - paths are relative to the referenced schema
|
|
625
|
-
report.schemaPath = [];
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
// follow schema.$recursiveRef keys
|
|
629
|
-
if (schema.$recursiveRef !== undefined) {
|
|
630
|
-
const applySiblingKeywordsWithRecursiveRef = this.options.version === 'draft2019-09' || this.options.version === 'draft2020-12';
|
|
631
|
-
if (applySiblingKeywordsWithRecursiveRef) {
|
|
632
|
-
const recursiveRefTarget = resolveRecursiveRef(schema, recursiveAnchorStack);
|
|
633
|
-
if (!recursiveRefTarget) {
|
|
634
|
-
report.addError('REF_UNRESOLVED', [schema.$recursiveRef], undefined, schema);
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
validate.call(this, report, recursiveRefTarget, json);
|
|
638
|
-
}
|
|
639
|
-
keys = keys.filter((key) => key !== '$recursiveRef');
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
// follow schema.$dynamicRef keys
|
|
643
|
-
if (schema.$dynamicRef !== undefined) {
|
|
644
|
-
const applySiblingKeywordsWithDynamicRef = this.options.version === 'draft2020-12';
|
|
645
|
-
if (applySiblingKeywordsWithDynamicRef) {
|
|
646
|
-
const dynamicRefTarget = resolveDynamicRef(schema, dynamicScopeStack);
|
|
647
|
-
if (typeof dynamicRefTarget === 'undefined') {
|
|
648
|
-
report.addError('REF_UNRESOLVED', [schema.$dynamicRef], undefined, schema);
|
|
649
|
-
}
|
|
650
|
-
else {
|
|
651
|
-
validate.call(this, report, dynamicRefTarget, json);
|
|
652
|
-
}
|
|
653
|
-
keys = keys.filter((key) => key !== '$dynamicRef');
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
const validationVocabularyEnabled = isValidationVocabularyEnabled(schema, report, this.options.version);
|
|
657
|
-
if (!validationVocabularyEnabled) {
|
|
658
|
-
keys = keys.filter((key) => !VALIDATION_VOCAB_KEYWORDS.has(key));
|
|
659
|
-
}
|
|
660
|
-
// type checking first
|
|
661
|
-
if (validationVocabularyEnabled && schema.type) {
|
|
662
|
-
keys.splice(keys.indexOf('type'), 1);
|
|
663
|
-
report.schemaPath.push('type');
|
|
664
|
-
JsonValidators.type.call(this, report, schema, json);
|
|
665
|
-
report.schemaPath.pop();
|
|
666
|
-
if (report.errors.length && this.options.breakOnFirstError) {
|
|
667
|
-
if (pushedRecursiveAnchor) {
|
|
668
|
-
recursiveAnchorStack.pop();
|
|
669
|
-
}
|
|
670
|
-
if (pushedDynamicScope) {
|
|
671
|
-
dynamicScopeStack.pop();
|
|
672
|
-
}
|
|
673
|
-
return false;
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
// now iterate all the keys in schema and execute validation methods
|
|
677
|
-
// Defer unevaluatedItems/unevaluatedProperties to run after other validators,
|
|
678
|
-
// so combinator validation results are cached and available for annotation collection
|
|
679
|
-
const deferredUnevaluatedKeys = [];
|
|
680
|
-
for (const key of keys) {
|
|
681
|
-
if (key === 'unevaluatedItems' || key === 'unevaluatedProperties') {
|
|
682
|
-
deferredUnevaluatedKeys.push(key);
|
|
683
|
-
continue;
|
|
684
|
-
}
|
|
685
|
-
const validator = JsonValidators[key];
|
|
686
|
-
if (validator) {
|
|
687
|
-
validator.call(this, report, schema, json);
|
|
688
|
-
if (report.errors.length && this.options.breakOnFirstError) {
|
|
689
|
-
break;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
// Run unevaluated* validators after all others have cached their combinator results
|
|
694
|
-
if (deferredUnevaluatedKeys.length > 0 && !(report.errors.length > 0 && this.options.breakOnFirstError)) {
|
|
695
|
-
for (const key of deferredUnevaluatedKeys) {
|
|
696
|
-
const validator = JsonValidators[key];
|
|
697
|
-
if (validator) {
|
|
698
|
-
validator.call(this, report, schema, json);
|
|
699
|
-
if (report.errors.length && this.options.breakOnFirstError) {
|
|
700
|
-
break;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
if (report.errors.length === 0 || this.options.breakOnFirstError === false) {
|
|
706
|
-
if (Array.isArray(json)) {
|
|
707
|
-
recurseArray.call(this, report, schema, json);
|
|
708
|
-
}
|
|
709
|
-
else if (isObject(json)) {
|
|
710
|
-
recurseObject.call(this, report, schema, json);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
if (typeof this.options.customValidator === 'function') {
|
|
714
|
-
this.options.customValidator.call(this, report, schema, json);
|
|
715
|
-
}
|
|
716
|
-
if (pushedRecursiveAnchor) {
|
|
717
|
-
recursiveAnchorStack.pop();
|
|
718
|
-
}
|
|
719
|
-
if (pushedDynamicScope) {
|
|
720
|
-
dynamicScopeStack.pop();
|
|
721
|
-
}
|
|
722
|
-
// we don't need the root pointer anymore
|
|
723
|
-
if (isRoot) {
|
|
724
|
-
report.rootSchema = undefined;
|
|
725
|
-
}
|
|
726
|
-
// return valid just to be able to break at some code points
|
|
727
|
-
return report.errors.length === 0;
|
|
728
|
-
}
|