Skip to content

Commit

Permalink
feat: anyRequired keyword, closes #85
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Feb 9, 2019
1 parent 87a637f commit 4bc66b4
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 0 deletions.
25 changes: 25 additions & 0 deletions README.md
Expand Up @@ -28,6 +28,7 @@ Custom JSON-Schema keywords for [Ajv](https://github.com/epoberezkin/ajv) valida
- [uniqueItemProperties](#uniqueitemproperties)
- [Keywords for objects](#keywords-for-objects)
- [allRequired](allrequired)
- [anyRequired](anyrequired)
- [patternRequired](#patternrequired)
- [prohibited](#prohibited)
- [deepProperties](#deepproperties)
Expand Down Expand Up @@ -338,6 +339,28 @@ var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
```


#### `anyRequired`

This keyword allows to require the presence of any (at least one) property from the list.

This keyword applies only to objects. If the data is not an object, the validation succeeds.

The value of this keyword must be an array of strings, each string being a property name. For data object to be valid at least one of the properties in this array should be present in the object.

```javascript
var schema = {
anyRequired: ['foo', 'bar']
};

var validData = { foo: 1 };
var alsoValidData = { foo: 1, bar: 2 };

var invalidDataList = [ {}, { baz: 3 } ];
```

__Please note__: By combining `anyRequired` with `maxProperties: 1` you can achieve that exactly one property from the list is required to be present for the data object to pass validation.


#### `patternRequired`

This keyword allows to require the presence of properties that match some pattern(s).
Expand Down Expand Up @@ -379,6 +402,8 @@ var invalidDataList = [
];
```

__Please note__: `{prohibited: ['foo', 'bar']}` is equivalent to `{not: {anyRequired: ['foo', 'bar']}}` (i.e. it has the same validation result for any data).


#### `deepProperties`

Expand Down
24 changes: 24 additions & 0 deletions keywords/anyRequired.js
@@ -0,0 +1,24 @@
'use strict';

module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'object',
macro: function (schema) {
if (schema.length == 0) return {};
if (schema.length == 1) return { required: schema };
var schemas = schema.map(function (prop) {
return { required: [prop] };
});
return { anyOf: schemas };
},
metaSchema: {
type: 'array',
items: {
type: 'string'
}
}
};

ajv.addKeyword('anyRequired', defFunc.definition);
return ajv;
};
1 change: 1 addition & 0 deletions keywords/index.js
Expand Up @@ -7,6 +7,7 @@ module.exports = {
'typeof': require('./typeof'),
dynamicDefaults: require('./dynamicDefaults'),
allRequired: require('./allRequired'),
anyRequired: require('./anyRequired'),
prohibited: require('./prohibited'),
uniqueItemProperties: require('./uniqueItemProperties'),
deepProperties: require('./deepProperties'),
Expand Down
1 change: 1 addition & 0 deletions spec/schema-tests.spec.js
Expand Up @@ -7,6 +7,7 @@ var defineKeywords = require('..');
var ajvs = [
defineKeywords(getAjv(), [
'allRequired',
'anyRequired',
'deepProperties',
'deepRequired',
'formatMaximum',
Expand Down
86 changes: 86 additions & 0 deletions spec/tests/anyRequired.json
@@ -0,0 +1,86 @@
[
{
"description": "anyRequired requires that at least on property in the list is present",
"schema": {
"anyRequired": ["foo"]
},
"tests": [
{
"description": "property present is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "property present with an additional property is valid",
"data": {"foo": 1, "baz": 3},
"valid": true
},
{
"description": "no property present is invalid",
"data": { "baz": 1 },
"valid": false
},
{
"description": "empty object is invalid",
"data": {},
"valid": false
}
]
},
{
"description": "multiple properties in prohibited",
"schema": {
"anyRequired": ["foo", "bar"]
},
"tests": [
{
"description": "property present is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "property present with an additional property is valid",
"data": {"foo": 1, "baz": 3},
"valid": true
},
{
"description": "all properties present is valid",
"data": {"foo": 1, "bar": 2},
"valid": true
},
{
"description": "all properties present with an additional property is valid",
"data": {"foo": 1, "bar": 2, "baz": 3},
"valid": true
},
{
"description": "no property present is invalid",
"data": {"baz": 3},
"valid": false
},
{
"description": "empty object is invalid",
"data": {},
"valid": false
}
]
},
{
"description": "anyRequired: [] is always valid",
"schema": {
"anyRequired": []
},
"tests": [
{
"description": "any object is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "empty object is valid",
"data": {},
"valid": true
}
]
}
]

0 comments on commit 4bc66b4

Please sign in to comment.