patternRequired keyword (v5 proposal), closes #123
parent
dfe773735f
commit
ec0f1c1b22
41
KEYWORDS.md
41
KEYWORDS.md
|
@ -31,6 +31,7 @@ The keywords and their values define what rules the data should satisfy to be va
|
|||
- [additionalProperties](#additionalproperties)
|
||||
- [dependencies](#dependencies)
|
||||
- [patternGroups](#patterngroups-v5-proposal) (v5)
|
||||
- [patternRequired](#patternrequired-v5-proposal) (v5)
|
||||
- [Keywords for all types](#keywords-for-all-types)
|
||||
- [enum](#enum)
|
||||
- [constant](#constant-v5-proposal) (v5)
|
||||
|
@ -270,7 +271,7 @@ __Examples__
|
|||
|
||||
|
||||
2. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{ "type": "integer" },
|
||||
|
@ -308,7 +309,7 @@ __Examples__
|
|||
|
||||
|
||||
2. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"items": { "type": "integer" },
|
||||
"additionalItems": { "type": "string" }
|
||||
|
@ -321,7 +322,7 @@ __Examples__
|
|||
|
||||
|
||||
3. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{ "type": "integer" },
|
||||
|
@ -337,7 +338,7 @@ __Examples__
|
|||
|
||||
|
||||
4. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{ "type": "integer" },
|
||||
|
@ -476,7 +477,7 @@ If the value is a schema for the data object to be valid the values in all "addi
|
|||
__Examples__
|
||||
|
||||
1. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"properties": {
|
||||
"foo": { "type": "number" }
|
||||
|
@ -493,7 +494,7 @@ __Examples__
|
|||
_invalid_: `{"a": 3}`, `{"foo": 1, "baz": 3}`
|
||||
|
||||
2. _schema_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"properties": {
|
||||
"foo": { "type": "number" }
|
||||
|
@ -523,7 +524,7 @@ For schema dependency, if the data object contains a property that is a key in t
|
|||
__Examples__
|
||||
|
||||
1. _schema (property dependency)_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"foo": ["bar", "baz"]
|
||||
|
@ -537,7 +538,7 @@ __Examples__
|
|||
|
||||
|
||||
2. _schema (schema dependency)_:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"foo": {
|
||||
|
@ -588,6 +589,28 @@ _invalid_: `{}`, `{ "foo": "bar" }`, `{ "1": "2" }`
|
|||
|
||||
|
||||
|
||||
### patternRequired (v5 proposal)
|
||||
|
||||
The value of this keyword should be an array of strings, each string being a regular expression. For data object to be valid each regular expression in this array should match at least one property name in the data object.
|
||||
|
||||
If the array contains multiple regular expressions, more than one expression can match the same property name.
|
||||
|
||||
__Examples__
|
||||
|
||||
1. _schema_: `{ "patternRequired": [ "f.*o" ] }`
|
||||
|
||||
_valid_: `{ "foo": 1 }`, `{ "-fo-": 1 }`, { "foo": 1, "bar": 2 }`, any non-object
|
||||
|
||||
_invalid_: `{}`, `{ "bar": 2 }`, `{ "Foo": 1 }`,
|
||||
|
||||
2. _schema_: `{ "patternRequired": [ "f.*o", "b.*r" ] }`
|
||||
|
||||
_valid_: { "foo": 1, "bar": 2 }`, `{ "foobar": 3 }`, any non-object
|
||||
|
||||
_invalid_: `{}`, `{ "foo": 1 }`, `{ "bar": 2 }`
|
||||
|
||||
|
||||
|
||||
## Keywords for all types
|
||||
|
||||
### `enum`
|
||||
|
@ -655,7 +678,7 @@ __Examples__
|
|||
|
||||
2. _schema_:
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"not": {
|
||||
"items": {
|
||||
|
|
|
@ -53,7 +53,7 @@ It uses [doT templates](https://github.com/olado/doT) to generate super-fast val
|
|||
- [assigning defaults](#assigning-defaults) to missing properties and items
|
||||
- NEW: [coercing data](#coercing-data-types) to the types specified in `type` keywords
|
||||
- [custom keywords](#defining-custom-keywords)
|
||||
- keywords `switch`, `constant`, `contains`, `patternGroups`, `formatMaximum` / `formatMinimum` and `exclusiveFormatMaximum` / `exclusiveFormatMinimum` from [JSON-schema v5 proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) with [option v5](#options)
|
||||
- keywords `switch`, `constant`, `contains`, `patternGroups`, `patternRequired`, `formatMaximum` / `formatMinimum` and `exclusiveFormatMaximum` / `exclusiveFormatMinimum` from [JSON-schema v5 proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) with [option v5](#options)
|
||||
- [v5 meta-schema](https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#) for schemas using v5 keywords
|
||||
- NEW: [v5 $data reference](#data-reference) to use values from the validated data as values for the schema keywords
|
||||
- NEW: [asynchronous validation](#asynchronous-validation) of custom formats and keywords
|
||||
|
@ -160,6 +160,7 @@ With option `v5: true` Ajv also supports all validation keywords and [$data refe
|
|||
- [contains](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#contains-v5-proposal) - check that array contains a valid item
|
||||
- [constant](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#constant-v5-proposal) - check that data is equal to some value
|
||||
- [patternGroups](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#patterngroups-v5-proposal) - a more powerful alternative to patternProperties
|
||||
- [patternRequired](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#patternrequired-v5-proposal) - like `required` but with patterns that some property should match.
|
||||
- [formatMaximum, formatMinimum, exclusiveFormatMaximum, exclusiveFormatMinimum](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#formatmaximum--formatminimum-and-exclusiveformatmaximum--exclusiveformatminimum-v5-proposal) - setting limits for date, time, etc.
|
||||
|
||||
See [JSON-Schema validation keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md) for more details.
|
||||
|
@ -766,7 +767,7 @@ Defaults:
|
|||
|
||||
##### Validation and reporting options
|
||||
|
||||
- _v5_: add keywords `switch`, `constant`, `contains`, `patternGroups`, `formatMaximum` / `formatMinimum` and `exclusiveFormatMaximum` / `exclusiveFormatMinimum` from [JSON-schema v5 proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals). With this option added schemas without `$schema` property are validated against [v5 meta-schema](https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#). `false` by default.
|
||||
- _v5_: add keywords `switch`, `constant`, `contains`, `patternGroups`, `patternRequired`, `formatMaximum` / `formatMinimum` and `exclusiveFormatMaximum` / `exclusiveFormatMinimum` from [JSON-schema v5 proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals). With this option added schemas without `$schema` property are validated against [v5 meta-schema](https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#). `false` by default.
|
||||
- _allErrors_: check all rules collecting all errors. Default is to return after the first error.
|
||||
- _verbose_: include the reference to the part of the schema (`schema` and `parentSchema`) and validated data in errors (false by default).
|
||||
- _jsonPointers_: set `dataPath` propery of errors using [JSON Pointers](https://tools.ietf.org/html/rfc6901) instead of JavaScript property access notation.
|
||||
|
@ -874,6 +875,7 @@ Properties of `params` object in errors depend on the keyword that failed valida
|
|||
- `multipleOf` - property `multipleOf` (the schema of the keyword)
|
||||
- `pattern` - property `pattern` (the schema of the keyword)
|
||||
- `required` - property `missingProperty` (required property that is missing).
|
||||
- `patternRequired` (with v5 option) - property `missingPattern` (required pattern that did not match any property).
|
||||
- `type` - property `type` (required type(s), a string, can be a comma-separated list)
|
||||
- `uniqueItems` - properties `i` and `j` (indices of duplicate items).
|
||||
- `$ref` - property `ref` with the referenced schema URI.
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
uniqueItems: "'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)'",
|
||||
custom: "'should pass \"{{=$rule.keyword}}\" keyword validation'",
|
||||
patternGroups: "'should NOT have {{=$moreOrLess}} than {{=$limit}} properties matching pattern \"{{=it.util.escapeQuotes($pgProperty)}}\"'",
|
||||
patternRequired: "'should have property matching pattern \\'{{=$missingPattern}}\\''",
|
||||
switch: "'should pass \"switch\" keyword validation'",
|
||||
constant: "'should be equal to constant'",
|
||||
_formatLimit: "'should be {{=$opStr}} \"{{#def.concatSchemaEQ}}\"'",
|
||||
|
@ -144,6 +145,7 @@
|
|||
uniqueItems: "{{#def.schemaRefOrVal}}",
|
||||
custom: "validate.schema{{=$schemaPath}}",
|
||||
patternGroups: "validate.schema{{=$schemaPath}}",
|
||||
patternRequired: "validate.schema{{=$schemaPath}}",
|
||||
switch: "validate.schema{{=$schemaPath}}",
|
||||
constant: "validate.schema{{=$schemaPath}}",
|
||||
_formatLimit: "{{#def.schemaRefOrQS}}",
|
||||
|
@ -175,6 +177,7 @@
|
|||
uniqueItems: "{ i: i, j: j }",
|
||||
custom: "{ keyword: '{{=$rule.keyword}}' }",
|
||||
patternGroups: "{ reason: '{{=$reason}}', limit: {{=$limit}}, pattern: '{{=it.util.escapeQuotes($pgProperty)}}' }",
|
||||
patternRequired: "{ missingPattern: '{{=$missingPattern}}' }",
|
||||
switch: "{ caseIndex: {{=$caseIndex}} }",
|
||||
constant: "{}",
|
||||
_formatLimit: "{ limit: {{#def.schemaValueQS}} }",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
|
||||
{{
|
||||
var $key = 'key' + $lvl
|
||||
, $matched = 'patternMatched' + $lvl
|
||||
, $closingBraces = '';
|
||||
}}
|
||||
|
||||
var {{=$valid}} = true;
|
||||
{{~ $schema:$pProperty }}
|
||||
var {{=$matched}} = false;
|
||||
for (var {{=$key}} in {{=$data}}) {
|
||||
{{=$matched}} = {{= it.usePattern($pProperty) }}.test({{=$key}});
|
||||
if ({{=$matched}}) break;
|
||||
}
|
||||
|
||||
{{ var $missingPattern = it.util.escapeQuotes($pProperty); }}
|
||||
if (!{{=$matched}}) {
|
||||
{{=$valid}} = false;
|
||||
{{# def.addError:'patternRequired' }}
|
||||
} {{# def.elseIfValid }}
|
||||
{{~}}
|
||||
|
||||
{{= $closingBraces }}
|
29
lib/v5.js
29
lib/v5.js
|
@ -9,23 +9,42 @@ module.exports = {
|
|||
|
||||
|
||||
function enableV5(ajv) {
|
||||
var inlineFunctions = {
|
||||
'switch': require('./dotjs/switch'),
|
||||
'constant': require('./dotjs/constant'),
|
||||
'_formatLimit': require('./dotjs/_formatLimit'),
|
||||
'patternRequired': require('./dotjs/patternRequired')
|
||||
};
|
||||
|
||||
if (ajv._opts.meta !== false) {
|
||||
var metaSchema = require('./refs/json-schema-v5.json');
|
||||
ajv.addMetaSchema(metaSchema, META_SCHEMA_ID);
|
||||
}
|
||||
ajv.addKeyword('constant', { inline: require('./dotjs/constant'), statements: true, errors: 'full' });
|
||||
_addKeyword('constant');
|
||||
ajv.addKeyword('contains', { type: 'array', macro: containsMacro });
|
||||
|
||||
var formatLimit = require('./dotjs/_formatLimit');
|
||||
ajv.addKeyword('formatMaximum', { type: 'string', inline: formatLimit, statements: true, errors: 'full' });
|
||||
ajv.addKeyword('formatMinimum', { type: 'string', inline: formatLimit, statements: true, errors: 'full' });
|
||||
_addKeyword('formatMaximum', 'string', inlineFunctions._formatLimit);
|
||||
_addKeyword('formatMinimum', 'string', inlineFunctions._formatLimit);
|
||||
ajv.addKeyword('exclusiveFormatMaximum');
|
||||
ajv.addKeyword('exclusiveFormatMinimum');
|
||||
|
||||
ajv.addKeyword('patternGroups'); // implemented in properties.jst
|
||||
ajv.addKeyword('switch', { inline: require('./dotjs/switch'), statements: true, errors: 'full' });
|
||||
_addKeyword('patternRequired', 'object');
|
||||
_addKeyword('switch');
|
||||
|
||||
|
||||
function _addKeyword(keyword, types, inlineFunc) {
|
||||
var definition = {
|
||||
inline: inlineFunc || inlineFunctions[keyword],
|
||||
statements: true,
|
||||
errors: 'full'
|
||||
};
|
||||
if (types) definition.type = types;
|
||||
ajv.addKeyword(keyword, definition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function containsMacro(schema) {
|
||||
return {
|
||||
not: { items: { not: schema } }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ajv",
|
||||
"version": "3.7.2",
|
||||
"version": "3.8.0",
|
||||
"description": "Another JSON Schema Validator",
|
||||
"main": "lib/ajv.js",
|
||||
"files": [
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
[
|
||||
{
|
||||
"description": "patternRequired requires that some property matching pattern is present",
|
||||
"schema": {
|
||||
"patternRequired": [ "f.*o" ]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "property matching required pattern is valid",
|
||||
"data": { "foo": 1 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "one of properties matching required pattern is valid",
|
||||
"data": { "foo": 1, "bar": 2 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "non-present property matching required pattern is invalid",
|
||||
"data": { "bar": 1 },
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "multiple patterns in patternRequired",
|
||||
"schema": {
|
||||
"patternRequired": [ "a+", "b+" ]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "both patterns matched with one property is valid",
|
||||
"data": { "ab": 2 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "both patterns matched with separate properties is valid",
|
||||
"data": { "aa": 1, "bb": 2 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "both patterns matched with multiple properties is valid",
|
||||
"data": { "a": 1, "aa": 2, "ab": 3, "b": 4, "bb": 5 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "one pattern not matched is invalid",
|
||||
"data": { "aa": 1 },
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "another pattern not matched is invalid",
|
||||
"data": { "bb": 2 },
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "both patterns not matched is invalid",
|
||||
"data": { "c": 3 },
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "regexes in patternRequired are not anchored by default and are case sensitive",
|
||||
"schema": {
|
||||
"patternRequired": [ "X_[0-9]{2,}" ]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "regexes are not anchored",
|
||||
"data": { "aX_25b": 1 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive",
|
||||
"data": { "X_25": 2 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive, 2",
|
||||
"data": { "x_25": 3 },
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue