refactor: remove patternGroups keyword, #614
parent
18b4c3f3a4
commit
e15f543dbd
36
KEYWORDS.md
36
KEYWORDS.md
|
@ -31,7 +31,6 @@ The keywords and their values define what rules the data should satisfy to be va
|
|||
- [additionalProperties](#additionalproperties)
|
||||
- [dependencies](#dependencies)
|
||||
- [propertyNames](#propertynames) (added in draft-06)
|
||||
- [patternGroups](#patterngroups-deprecated) (deprecated)
|
||||
- [patternRequired](#patternrequired-proposed) (proposed)
|
||||
- [Keywords for all types](#keywords-for-all-types)
|
||||
- [enum](#enum)
|
||||
|
@ -617,41 +616,6 @@ _invalid_: `{"foo": "any value"}`
|
|||
|
||||
|
||||
|
||||
### `patternGroups` (deprecated)
|
||||
|
||||
This keyword is only provided for backward compatibility, it will be removed in the next major version. To use it, pass option `patternGroups: true`.
|
||||
|
||||
The value of this keyword should be a map where keys should be regular expressions and the values should be objects with the following properties:
|
||||
|
||||
- `schema` (required) - should be a JSON Schema. For data object to be valid the values in data object properties that match regular expression(s) should be valid according to the corresponding `schema`(s).
|
||||
- `maximum` / `minimum` (optional) - should be integers. For data object to be valid the number of properties that match regular expression(s) should be within limits set by `minimum`(s) and `maximum`(s).
|
||||
|
||||
|
||||
__Example__
|
||||
|
||||
_schema_:
|
||||
|
||||
```json
|
||||
{
|
||||
"patternGroups": {
|
||||
"^[a-z]+$": {
|
||||
"minimum": 1,
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
"^[0-9]+$": {
|
||||
"minimum": 1,
|
||||
"schema": { "type": "integer" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_valid_: `{ "foo": "bar", "1": "2" }`, any non-object
|
||||
|
||||
_invalid_: `{}`, `{ "foo": "bar" }`, `{ "1": "2" }`
|
||||
|
||||
|
||||
|
||||
### `patternRequired` (proposed)
|
||||
|
||||
Defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package.
|
||||
|
|
|
@ -225,8 +225,8 @@ declare namespace ajv {
|
|||
DependenciesParams | FormatParams | ComparisonParams |
|
||||
MultipleOfParams | PatternParams | RequiredParams |
|
||||
TypeParams | UniqueItemsParams | CustomParams |
|
||||
PatternGroupsParams | PatternRequiredParams |
|
||||
PropertyNamesParams | SwitchParams | NoParams | EnumParams;
|
||||
PatternRequiredParams | PropertyNamesParams |
|
||||
SwitchParams | NoParams | EnumParams;
|
||||
|
||||
interface RefParams {
|
||||
ref: string;
|
||||
|
@ -282,12 +282,6 @@ declare namespace ajv {
|
|||
keyword: string;
|
||||
}
|
||||
|
||||
interface PatternGroupsParams {
|
||||
reason: string;
|
||||
limit: number;
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
interface PatternRequiredParams {
|
||||
missingPattern: string;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ var compileSchema = require('./compile')
|
|||
, formats = require('./compile/formats')
|
||||
, rules = require('./compile/rules')
|
||||
, $dataMetaSchema = require('./data')
|
||||
, patternGroups = require('./patternGroups')
|
||||
, util = require('./compile/util');
|
||||
|
||||
module.exports = Ajv;
|
||||
|
@ -74,7 +73,6 @@ function Ajv(opts) {
|
|||
addDraft6MetaSchema(this);
|
||||
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
|
||||
addInitialSchemas(this);
|
||||
if (opts.patternGroups) patternGroups(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -111,7 +111,6 @@
|
|||
not: "'should NOT be valid'",
|
||||
oneOf: "'should match exactly one schema in oneOf'",
|
||||
pattern: "'should match pattern \"{{#def.concatSchemaEQ}}\"'",
|
||||
patternGroups: "'should NOT have {{=$moreOrLess}} than {{=$limit}} properties matching pattern \"{{=it.util.escapeQuotes($pgProperty)}}\"'",
|
||||
propertyNames: "'property name \\'{{=$invalidName}}\\' is invalid'",
|
||||
required: "'{{? it.opts._errorDataPathProperty }}is a required property{{??}}should have required property \\'{{=$missingProperty}}\\'{{?}}'",
|
||||
type: "'should be {{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}'",
|
||||
|
@ -148,7 +147,6 @@
|
|||
not: "validate.schema{{=$schemaPath}}",
|
||||
oneOf: "validate.schema{{=$schemaPath}}",
|
||||
pattern: "{{#def.schemaRefOrQS}}",
|
||||
patternGroups: "validate.schema{{=$schemaPath}}",
|
||||
propertyNames: "validate.schema{{=$schemaPath}}",
|
||||
required: "validate.schema{{=$schemaPath}}",
|
||||
type: "validate.schema{{=$schemaPath}}",
|
||||
|
@ -184,7 +182,6 @@
|
|||
not: "{}",
|
||||
oneOf: "{ passingSchemas: {{=$passingSchemas}} }",
|
||||
pattern: "{ pattern: {{#def.schemaValueQS}} }",
|
||||
patternGroups: "{ reason: '{{=$reason}}', limit: {{=$limit}}, pattern: '{{=it.util.escapeQuotes($pgProperty)}}' }",
|
||||
propertyNames: "{ propertyName: '{{=$invalidName}}' }",
|
||||
required: "{ missingProperty: '{{=$missingProperty}}' }",
|
||||
type: "{ type: '{{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}' }",
|
||||
|
|
|
@ -44,11 +44,6 @@
|
|||
var $required = it.schema.required;
|
||||
if ($required && !(it.opts.v5 && $required.$data) && $required.length < it.opts.loopRequired)
|
||||
var $requiredHash = it.util.toHash($required);
|
||||
|
||||
if (it.opts.patternGroups) {
|
||||
var $pgProperties = it.schema.patternGroups || {}
|
||||
, $pgPropertyKeys = Object.keys($pgProperties);
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
|
@ -76,11 +71,6 @@ var {{=$nextValid}} = true;
|
|||
|| {{= it.usePattern($pProperty) }}.test({{=$key}})
|
||||
{{~}}
|
||||
{{?}}
|
||||
{{? it.opts.patternGroups && $pgPropertyKeys.length }}
|
||||
{{~ $pgPropertyKeys:$pgProperty:$i }}
|
||||
|| {{= it.usePattern($pgProperty) }}.test({{=$key}})
|
||||
{{~}}
|
||||
{{?}}
|
||||
);
|
||||
|
||||
if (isAdditional{{=$lvl}}) {
|
||||
|
@ -246,79 +236,6 @@ var {{=$nextValid}} = true;
|
|||
{{?}}
|
||||
|
||||
|
||||
{{? it.opts.patternGroups && $pgPropertyKeys.length }}
|
||||
{{~ $pgPropertyKeys:$pgProperty }}
|
||||
{{
|
||||
var $pgSchema = $pgProperties[$pgProperty]
|
||||
, $sch = $pgSchema.schema;
|
||||
}}
|
||||
|
||||
{{? {{# def.nonEmptySchema:$sch}} }}
|
||||
{{
|
||||
$it.schema = $sch;
|
||||
$it.schemaPath = it.schemaPath + '.patternGroups' + it.util.getProperty($pgProperty) + '.schema';
|
||||
$it.errSchemaPath = it.errSchemaPath + '/patternGroups/'
|
||||
+ it.util.escapeFragment($pgProperty)
|
||||
+ '/schema';
|
||||
}}
|
||||
|
||||
var pgPropCount{{=$lvl}} = 0;
|
||||
|
||||
{{# def.iterateProperties }}
|
||||
if ({{= it.usePattern($pgProperty) }}.test({{=$key}})) {
|
||||
pgPropCount{{=$lvl}}++;
|
||||
|
||||
{{
|
||||
$it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
|
||||
var $passData = $data + '[' + $key + ']';
|
||||
$it.dataPathArr[$dataNxt] = $key;
|
||||
}}
|
||||
|
||||
{{# def.generateSubschemaCode }}
|
||||
{{# def.optimizeValidate }}
|
||||
|
||||
{{? $breakOnError }} if (!{{=$nextValid}}) break; {{?}}
|
||||
}
|
||||
{{? $breakOnError }} else {{=$nextValid}} = true; {{?}}
|
||||
}
|
||||
|
||||
{{# def.ifResultValid }}
|
||||
|
||||
{{
|
||||
var $pgMin = $pgSchema.minimum
|
||||
, $pgMax = $pgSchema.maximum;
|
||||
}}
|
||||
{{? $pgMin !== undefined || $pgMax !== undefined }}
|
||||
var {{=$valid}} = true;
|
||||
|
||||
{{ var $currErrSchemaPath = $errSchemaPath; }}
|
||||
|
||||
{{? $pgMin !== undefined }}
|
||||
{{ var $limit = $pgMin, $reason = 'minimum', $moreOrLess = 'less'; }}
|
||||
{{=$valid}} = pgPropCount{{=$lvl}} >= {{=$pgMin}};
|
||||
{{ $errSchemaPath = it.errSchemaPath + '/patternGroups/minimum'; }}
|
||||
{{# def.checkError:'patternGroups' }}
|
||||
{{? $pgMax !== undefined }}
|
||||
else
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
||||
{{? $pgMax !== undefined }}
|
||||
{{ var $limit = $pgMax, $reason = 'maximum', $moreOrLess = 'more'; }}
|
||||
{{=$valid}} = pgPropCount{{=$lvl}} <= {{=$pgMax}};
|
||||
{{ $errSchemaPath = it.errSchemaPath + '/patternGroups/maximum'; }}
|
||||
{{# def.checkError:'patternGroups' }}
|
||||
{{?}}
|
||||
|
||||
{{ $errSchemaPath = $currErrSchemaPath; }}
|
||||
|
||||
{{# def.ifValid }}
|
||||
{{?}}
|
||||
{{?}} {{ /* def.nonEmptySchema */ }}
|
||||
{{~}}
|
||||
{{?}}
|
||||
|
||||
|
||||
{{? $breakOnError }}
|
||||
{{= $closingBraces }}
|
||||
if ({{=$errs}} == errors) {
|
||||
|
|
|
@ -162,9 +162,6 @@
|
|||
{{ $closingBraces2 += '}'; }}
|
||||
{{?}}
|
||||
{{??}}
|
||||
{{? it.opts.v5 && it.schema.patternGroups }}
|
||||
{{ it.logger.warn('keyword "patternGroups" is deprecated and disabled. Use option patternGroups: true to enable.'); }}
|
||||
{{?}}
|
||||
{{~ it.RULES:$rulesGroup }}
|
||||
{{? $shouldUseGroup($rulesGroup) }}
|
||||
{{? $rulesGroup.type }}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
|
||||
|
||||
module.exports = function (ajv) {
|
||||
var defaultMeta = ajv._opts.defaultMeta;
|
||||
var metaSchemaRef = typeof defaultMeta == 'string'
|
||||
? { $ref: defaultMeta }
|
||||
: ajv.getSchema(META_SCHEMA_ID)
|
||||
? { $ref: META_SCHEMA_ID }
|
||||
: {};
|
||||
|
||||
ajv.addKeyword('patternGroups', {
|
||||
// implemented in properties.jst
|
||||
metaSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: 'object',
|
||||
required: [ 'schema' ],
|
||||
properties: {
|
||||
maximum: {
|
||||
type: 'integer',
|
||||
minimum: 0
|
||||
},
|
||||
minimum: {
|
||||
type: 'integer',
|
||||
minimum: 0
|
||||
},
|
||||
schema: metaSchemaRef
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
}
|
||||
});
|
||||
ajv.RULES.all.properties.implements.push('patternGroups');
|
||||
};
|
|
@ -8,7 +8,6 @@ var jsonSchemaTest = require('json-schema-test')
|
|||
|
||||
var instances = getAjvInstances(options, {
|
||||
$data: true,
|
||||
patternGroups: true,
|
||||
unknownFormats: ['allowedUnknown']
|
||||
});
|
||||
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
[
|
||||
{
|
||||
"description": "patternGroups validates properties matching a regex (equivalent to the test from draft 4)",
|
||||
"schema": {
|
||||
"patternGroups": {
|
||||
"f.*o": {
|
||||
"schema": {"type": "integer"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single valid match is valid",
|
||||
"data": {"foo": 1},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "multiple valid matches is valid",
|
||||
"data": {"foo": 1, "foooooo" : 2},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "a single invalid match is invalid",
|
||||
"data": {"foo": "bar", "fooooo": 2},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "multiple invalid matches is invalid",
|
||||
"data": {"foo": "bar", "foooooo" : "baz"},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "ignores non-objects",
|
||||
"data": 12,
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "multiple simultaneous patternGroups are validated (equivalent to the test from draft 4)",
|
||||
"schema": {
|
||||
"patternGroups": {
|
||||
"a*": {
|
||||
"schema": {"type": "integer"}
|
||||
},
|
||||
"aaa*": {
|
||||
"schema": {"maximum": 20}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single valid match is valid",
|
||||
"data": {"a": 21},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "a simultaneous match is valid",
|
||||
"data": {"aaaa": 18},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "multiple matches is valid",
|
||||
"data": {"a": 21, "aaaa": 18},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to one is invalid",
|
||||
"data": {"a": "bar"},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to the other is invalid",
|
||||
"data": {"aaaa": 31},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to both is invalid",
|
||||
"data": {"aaa": "foo", "aaaa": 31},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "regexes in patternGroups are not anchored by default and are case sensitive (equivalent to the test from draft 4)",
|
||||
"schema": {
|
||||
"patternGroups": {
|
||||
"[0-9]{2,}": {
|
||||
"schema": { "type": "boolean" }
|
||||
},
|
||||
"X_": {
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "non recognized members are ignored",
|
||||
"data": { "answer 1": "42" },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "recognized members are accounted for",
|
||||
"data": { "a31b": null },
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive",
|
||||
"data": { "a_x_3": 3 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive, 2",
|
||||
"data": { "a_X_3": 3 },
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description":
|
||||
"patternGroups validates that the number of properties matching a regex is within limit",
|
||||
"schema": {
|
||||
"patternGroups": {
|
||||
"f.*o": {
|
||||
"schema": {"type": "integer"},
|
||||
"minimum": 1,
|
||||
"maximum": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single valid match is valid",
|
||||
"data": {"foo": 1},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "2 valid matches are valid",
|
||||
"data": {"foo": 1, "foooo" : 2},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "no valid matches are invalid",
|
||||
"data": {},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "more than 2 valid matches are invalid",
|
||||
"data": {"foo": 1, "foooo" : 2, "foooooo" : 3},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "sinlge invalid match is invalid",
|
||||
"data": {"foo": 1, "foooooo" : "baz"},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "multiple simultaneous patternGroups are validated for number of matching properties",
|
||||
"schema": {
|
||||
"patternGroups": {
|
||||
"a*": {
|
||||
"schema": {"type": "integer"},
|
||||
"minimum": 1
|
||||
},
|
||||
"aaa*": {
|
||||
"schema": {"maximum": 20},
|
||||
"maximum": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single first match is valid",
|
||||
"data": {"a": 21},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "no first match is invalid",
|
||||
"data": {},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "simultaneous match is valid",
|
||||
"data": {"aaaa": 18},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "multiple matches is valid",
|
||||
"data": {"a": 21, "aaaa": 18},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "two second matches are invalid",
|
||||
"data": {"aaa": 17, "aaaa": 18},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "invalid due to the first is invalid",
|
||||
"data": {"a": "bar"},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "invalid due to the second is invalid",
|
||||
"data": {"a": 21, "aaaa": 31},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "invalid due to both is invalid",
|
||||
"data": {"a": "foo", "aaaa": 31},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "properties, patternGroups, additionalProperties interaction (equivalent to the test from draft 4)",
|
||||
"schema": {
|
||||
"properties": {
|
||||
"foo": {"type": "array", "maxItems": 3},
|
||||
"bar": {"type": "array"}
|
||||
},
|
||||
"patternGroups": {
|
||||
"f.o": { "schema": {"minItems": 2} }
|
||||
},
|
||||
"additionalProperties": {"type": "integer"}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "property validates property",
|
||||
"data": {"foo": [1, 2]},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "property invalidates property",
|
||||
"data": {"foo": [1, 2, 3, 4]},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "patternGroups invalidates property",
|
||||
"data": {"foo": []},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "patternGroups validates nonproperty",
|
||||
"data": {"fxo": [1, 2]},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "patternGroups invalidates nonproperty",
|
||||
"data": {"fxo": []},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "additionalProperty ignores property",
|
||||
"data": {"bar": []},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "additionalProperty validates others",
|
||||
"data": {"quux": 3},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "additionalProperty invalidates others",
|
||||
"data": {"quux": "foo"},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -222,21 +222,6 @@ describe('Ajv Options', function () {
|
|||
test(schema, obj, proto);
|
||||
});
|
||||
|
||||
it('should only validate own properties with patternGroups', function() {
|
||||
ajv = new Ajv({ allErrors: true, patternGroups: true });
|
||||
ajvOP = new Ajv({ ownProperties: true, allErrors: true, patternGroups: true });
|
||||
|
||||
var schema = {
|
||||
patternGroups: {
|
||||
'f.*o': { schema: { type: 'integer' } }
|
||||
}
|
||||
};
|
||||
|
||||
var obj = { fooo: 1 };
|
||||
var proto = { foo: 'not a number' };
|
||||
test(schema, obj, proto);
|
||||
});
|
||||
|
||||
it('should only validate own properties with propertyNames', function() {
|
||||
var schema = {
|
||||
propertyNames: {
|
||||
|
@ -1148,61 +1133,6 @@ describe('Ajv Options', function () {
|
|||
});
|
||||
|
||||
|
||||
describe('patternGroups without draft-07 meta-schema', function() {
|
||||
it('should use default meta-schema', function() {
|
||||
var ajv = new Ajv({
|
||||
patternGroups: true,
|
||||
meta: require('../lib/refs/json-schema-draft-04.json')
|
||||
});
|
||||
|
||||
ajv.compile({
|
||||
patternGroups: {
|
||||
'^foo': {
|
||||
schema: { type: 'number' },
|
||||
minimum: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
should.throw(function() {
|
||||
ajv.compile({
|
||||
patternGroups: {
|
||||
'^foo': {
|
||||
schema: { type: 'wrong_type' },
|
||||
minimum: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not use meta-schema if not available', function() {
|
||||
var ajv = new Ajv({
|
||||
patternGroups: true,
|
||||
meta: false
|
||||
});
|
||||
|
||||
ajv.compile({
|
||||
patternGroups: {
|
||||
'^foo': {
|
||||
schema: { type: 'number' },
|
||||
minimum: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ajv.compile({
|
||||
patternGroups: {
|
||||
'^foo': {
|
||||
schema: { type: 'wrong_type' },
|
||||
minimum: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('schemaId', function() {
|
||||
describe('= undefined (default)', function() {
|
||||
it('should throw if both id and $id are available and different', function() {
|
||||
|
|
Loading…
Reference in New Issue