diff --git a/.eslintrc.yml b/.eslintrc.yml
index dfd66150d..9fe920d6a 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -5,7 +5,7 @@ env:
rules:
block-scoped-var: 2
callback-return: 2
- complexity: [2, 13]
+ complexity: [2, 16]
curly: [2, multi-or-nest, consistent]
dot-location: [2, property]
dot-notation: 2
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..88fc551fa
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+github: epoberezkin
+tidelift: "npm/ajv"
+open_collective: "ajv"
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 1deda1e23..558501036 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,11 +1,12 @@
@@ -15,7 +16,7 @@ This template is for bug reports. For other issues please use:
**Ajv options object**
-
+
```javascript
@@ -48,7 +49,7 @@ This template is for bug reports. For other issues please use:
+
+**What version of Ajv are you using? Does the issue happen if you use the latest version?**
+
+
+
+**Ajv options object**
+
+
+
+```javascript
+
+
+```
+
+
+**JSON Schema**
+
+
+
+```json
+
+
+```
+
+
+**Sample data**
+
+
+
+```json
+
+
+```
+
+
+**Your code**
+
+
+
+```javascript
+
+
+```
+
+
+**Validation result, data AFTER validation, error messages**
+
+```
+
+
+```
+
+**What results did you expect?**
+
+
+**Are you going to resolve the issue?**
diff --git a/.github/ISSUE_TEMPLATE/change.md b/.github/ISSUE_TEMPLATE/change.md
new file mode 100644
index 000000000..0c8035d1a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/change.md
@@ -0,0 +1,24 @@
+---
+name: Feature or change proposal
+about: For proposals of new features, options or some other improvements
+title: ''
+labels: 'enhancement'
+assignees: ''
+
+---
+
+
+
+**What version of Ajv you are you using?**
+
+**What problem do you want to solve?**
+
+**What do you think is the correct solution to problem?**
+
+**Will you be able to implement it?**
diff --git a/.github/ISSUE_TEMPLATE/compatibility.md b/.github/ISSUE_TEMPLATE/compatibility.md
new file mode 100644
index 000000000..79aa63999
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/compatibility.md
@@ -0,0 +1,28 @@
+---
+name: Browser and compatibility issue
+about: For issues that only happen in a specific environment
+title: ''
+labels: 'compatibility'
+assignees: ''
+
+---
+
+
+
+**The version of Ajv you are using**
+
+**The environment you have the problem with**
+
+**Your code (please make it as small as possible to reproduce the issue)**
+
+**If your issue is in the browser, please list the other packages loaded in the page in the order they are loaded. Please check if the issue gets resolved (or results change) if you move Ajv bundle closer to the top**
+
+**Results in node.js v8+**
+
+**Results and error messages in your platform**
diff --git a/.github/ISSUE_TEMPLATE/installation.md b/.github/ISSUE_TEMPLATE/installation.md
new file mode 100644
index 000000000..1786e9f2f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/installation.md
@@ -0,0 +1,33 @@
+---
+name: Installation and dependency issue
+about: For issues that happen during installation
+title: ''
+labels: 'installation'
+assignees: ''
+
+---
+
+
+
+**The version of Ajv you are using**
+
+**Operating system and node.js version**
+
+**Package manager and its version**
+
+**Link to (or contents of) package.json**
+
+**Error messages**
+
+**The output of `npm ls`**
diff --git a/.github/ISSUE_TEMPLATE/typescript.md b/.github/ISSUE_TEMPLATE/typescript.md
new file mode 100644
index 000000000..de3c20168
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/typescript.md
@@ -0,0 +1,42 @@
+---
+name: Missing or incorrect type definition
+about: Please use for issues related to typescript types
+title: ''
+labels: 'typescript'
+assignees: ''
+
+---
+
+
+
+**What version of Ajv are you using? Does the issue happen if you use the latest version?**
+
+
+**Your typescript code**
+
+
+
+```typescript
+
+
+```
+
+
+**Typescript compiler error messages**
+
+```
+
+
+```
+
+**Describe the change that should be made to address the issue?**
+
+
+**Are you going to resolve the issue?**
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index d7feecdbd..7abf655f1 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -2,7 +2,7 @@
Thank you for submitting a pull request to Ajv.
Before continuing, please read the guidelines:
-https://github.com/epoberezkin/ajv/blob/master/CONTRIBUTING.md#pull-requests
+https://github.com/ajv-validator/ajv/blob/master/CONTRIBUTING.md#pull-requests
If the pull request contains code please make sure there is an issue that we agreed to resolve (if it is a documentation improvement there is no need for an issue).
diff --git a/.github/config.yml b/.github/config.yml
new file mode 100644
index 000000000..1f6c1054f
--- /dev/null
+++ b/.github/config.yml
@@ -0,0 +1,32 @@
+# Please supply comments to be used for GitHub labels
+githubLabels:
+ bug: >
+ Bug confirmed - to be fixed. PR is welcome!
+
+# duplicate: >
+# enhancement: >
+# good first issue: >
+# help wanted: >
+# invalid: >
+# question: >
+# wont fix: >
+
+ bug report: >
+ Thank you for the report! If you didn't post a code sample to RunKit yet,
+ please clone this notebook https://runkit.com/esp/ajv-issue,
+ post the code sample that demonstrates the bug and post the link here.
+ It will speed up the investigation and fixing!
+
+ json schema: >
+ This question is about the usage of JSON Schema specification - it is not specific to Ajv.
+ Please use JSON Schema reference materials or [submit the question to Stack Overflow](https://stackoverflow.com/questions/ask?tags=jsonschema,ajv).
+
+ - [JSON Schema specification](http://json-schema.org/)
+
+ - [Tutorial by Space Telescope Science Institute](http://json-schema.org/understanding-json-schema/)
+
+ - [validation keywords](https://github.com/ajv-validator/ajv#validation-keywords) (in Ajv docs)
+
+ - [combining schemas](https://github.com/ajv-validator/ajv#ref) (in Ajv docs)
+
+ - [Tutorial by @epoberezkin](https://code.tutsplus.com/tutorials/validating-data-with-json-schema-part-1--cms-25343)
diff --git a/.gitignore b/.gitignore
index e2a293b92..b7f774a0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,5 @@ lib/dotjs/*.js
# bundles
dist/
+
+package-lock.json
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 000000000..43c97e719
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/.travis.yml b/.travis.yml
index 0ada0bbab..80bb5bf49 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,14 +3,14 @@ before_script:
- git submodule update --init
- npm install -g codeclimate-test-reporter
node_js:
- - "4"
- - "6"
- - "7"
- - "8"
+ - 10
+ - 12
+ - 14
after_script:
- codeclimate-test-reporter < coverage/lcov.info
- coveralls < coverage/lcov.info
- scripts/travis-gh-pages
+ - scripts/publish-built-version
notifications:
webhooks:
urls:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..410cda641
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ajv.validator@gmail.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/COERCION.md b/COERCION.md
index f310c2d67..6a0a41a68 100644
--- a/COERCION.md
+++ b/COERCION.md
@@ -1,6 +1,6 @@
# Ajv type coercion rules
-To enable type coercion pass option `coerceTypes` to Ajv with `true` or `array` (it is `false` by default). See [example](https://github.com/epoberezkin/ajv#coercing-data-types).
+To enable type coercion pass option `coerceTypes` to Ajv with `true` or `array` (it is `false` by default). See [example](https://github.com/ajv-validator/ajv#coercing-data-types).
The coercion rules are different from JavaScript:
- to validate user input as expected
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d6872665e..4f2f8aaed 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,9 +5,11 @@ Thank you for your help making Ajv better! Every contribution is appreciated. If
- [Documentation](#documentation)
- [Issues](#issues)
- [Bug reports](#bug-reports)
+ - [Security vulnerabilities](#security-vulnerabilities)
- [Change proposals](#changes)
- [Browser and compatibility issues](#compatibility)
- - [JSON schema standard](#json-schema)
+ - [Installation and dependency issues](#installation)
+ - [JSON Schema standard](#json-schema)
- [Ajv usage questions](#usage)
- [Code](#code)
- [Development](#development)
@@ -22,7 +24,7 @@ Ajv has a lot of features and maintaining documentation takes time. I appreciate
## Issues
-Before submitting the issue please search the existing issues and also review [Frequently Asked Questions](https://github.com/epoberezkin/ajv/blob/master/FAQ.md).
+Before submitting the issue please search the existing issues and also review [Frequently Asked Questions](https://github.com/ajv-validator/ajv/blob/master/FAQ.md).
I would really appreciate the time you spend providing all the information and reducing both your schema and data to the smallest possible size when they still have the issue. Simplifying the issue also makes it more valuable for other users (in cases it turns out to be an incorrect usage rather than a bug).
@@ -32,18 +34,29 @@ I would really appreciate the time you spend providing all the information and r
Please make sure to include the following information in the issue:
1. What version of Ajv are you using? Does the issue happen if you use the latest version?
-2. Ajv options object (see https://github.com/epoberezkin/ajv#options).
-3. JSON schema and the data you are validating (please make it as small as possible to reproduce the issue).
+2. Ajv options object (see https://github.com/ajv-validator/ajv#options).
+3. JSON Schema and the data you are validating (please make it as small as possible to reproduce the issue).
4. Your code (please use `options`, `schema` and `data` as variables).
5. Validation result, data AFTER validation, error messages.
6. What results did you expect?
-[Create bug report](https://github.com/epoberezkin/ajv/issues/new).
+Please include the link to the working code sample at Runkit.com (please clone https://runkit.com/esp/ajv-issue) - it will speed up investigation and fixing.
+
+[Create bug report](https://github.com/ajv-validator/ajv/issues/new?template=bug-or-error-report.md).
+
+
+#### Security vulnerabilities
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
+
+Please do NOT report security vulnerabilities via GitHub issues.
#### Change proposals
-[Create a proposal](https://github.com/epoberezkin/ajv/issues/new?labels=suggestion&body=**What%20version%20of%20Ajv%20you%20are%20you%20using%3F**%0A%0A**What%20problem%20do%20you%20want%20to%20solve%3F**%0A%0A**What%20do%20you%20think%20is%20the%20correct%20solution%20to%20problem?**%0A%0A**Will%20you%20be%20able%20to%20implement%20it%3F**%0A%0A) for a new feature, option or some other improvement.
+[Create a proposal](https://github.com/ajv-validator/ajv/issues/new?template=change.md) for a new feature, option or some other improvement.
Please include this information:
@@ -63,7 +76,7 @@ Please include as much details as possible.
#### Browser and compatibility issues
-[Create an issue](https://github.com/epoberezkin/ajv/issues/new?labels=compatibility&body=**The%20version%20of%20Ajv%20you%20are%20using**%0A%0A**The%20environment%20you%20have%20the%20problem%20with.**%0A%0A**Your%20code%20(please%20make%20it%20as%20small%20as%20possible%20to%20reproduce%20the%20issue).**%0A%0A**If%20your%20issue%20is%20in%20the%20browser,%20please%20list%20the%20other%20packages%20loaded%20in%20the%20page%20in%20the%20order%20they%20are%20loaded.%20Please%20check%20if%20the%20issue%20gets%20resolved%20(or%20results%20change)%20if%20you%20move%20Ajv%20bundle%20closer%20to%20the%20top.**%0A%0A**Results%20in%20node.js%20v4.**%0A%0A**Results%20and%20error%20messages%20in%20your%20platform.**%0A%0A) to report a compatibility problem that only happens in a particular environemnt (when your code works correctly in node.js v4 in linux systems but fails in some other environment).
+[Create an issue](https://github.com/ajv-validator/ajv/issues/new?template=compatibility.md) to report a compatibility problem that only happens in a particular environment (when your code works correctly in node.js v8+ in linux systems but fails in some other environment).
Please include this information:
@@ -71,17 +84,34 @@ Please include this information:
2. The environment you have the problem with.
3. Your code (please make it as small as possible to reproduce the issue).
4. If your issue is in the browser, please list the other packages loaded in the page in the order they are loaded. Please check if the issue gets resolved (or results change) if you move Ajv bundle closer to the top.
-5. Results in node.js v4.
+5. Results in node.js v8+.
6. Results and error messages in your platform.
-#### Using JSON schema standard
+#### Installation and dependency issues
+
+[Create an issue](https://github.com/ajv-validator/ajv/issues/new?template=installation.md) to report problems that happen during Ajv installation or when Ajv is missing some dependency.
+
+Before submitting the issue, please try the following:
+- use the latest stable Node.js and `npm`
+- use `yarn` instead of `npm` - the issue can be related to https://github.com/npm/npm/issues/19877
+- remove `node_modules` and `package-lock.json` and run install again
+
+If nothing helps, please submit:
+
+1. The version of Ajv you are using
+2. Operating system and node.js version
+3. Package manager and its version
+4. Link to (or contents of) package.json
+5. Error messages
+6. The output of `npm ls`
+
-Ajv implements JSON schema standard draft 4 and the proposed extensions for the next version of the standard (available when you use the option `v5: true`).
+#### Using JSON Schema standard
-If the issue is related to using v5 extensions please submit it as a [bug report](https://github.com/epoberezkin/ajv/issues/new).
+Ajv implements JSON Schema standard draft-04 and draft-06/07.
-If it is a general issue related to using the standard keywords included in JSON Schema or implementing some advanced validation logic please ask the question on [Stack Overflow](http://stackoverflow.com/questions/ask?tags=jsonschema,ajv) (my account is [esp](http://stackoverflow.com/users/1816503/esp)) or submitting the question to [JSON-Schema.org](https://github.com/json-schema-org/json-schema-spec/issues/new). Please mention @epoberezkin.
+If it is a general issue related to using the standard keywords included in JSON Schema or implementing some advanced validation logic please ask the question on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=jsonschema,ajv) (my account is [esp](https://stackoverflow.com/users/1816503/esp)) or submitting the question to [JSON-Schema.org](https://github.com/json-schema-org/json-schema-spec/issues/new). Please mention @epoberezkin.
#### Ajv usage questions
@@ -113,9 +143,9 @@ npm run test-fast
git commit -nm 'type: message'
```
-All validation functions are generated using doT templates in [dot](https://github.com/epoberezkin/ajv/tree/master/lib/dot) folder. Templates are precompiled so doT is not a run-time dependency.
+All validation functions are generated using doT templates in [dot](https://github.com/ajv-validator/ajv/tree/master/lib/dot) folder. Templates are precompiled so doT is not a run-time dependency.
-`npm run build` - compiles templates to [dotjs](https://github.com/epoberezkin/ajv/tree/master/lib/dotjs) folder.
+`npm run build` - compiles templates to [dotjs](https://github.com/ajv-validator/ajv/tree/master/lib/dotjs) folder.
`npm run watch` - automatically compiles templates when files in dot folder change
@@ -124,7 +154,7 @@ All validation functions are generated using doT templates in [dot](https://gith
To make accepting your changes faster please follow these steps:
-1. Submit an [issue with the bug](https://github.com/epoberezkin/ajv/issues/new) or with the proposed change (unless the contribution is to fix the documentation typos and mistakes).
+1. Submit an [issue with the bug](https://github.com/ajv-validator/ajv/issues/new) or with the proposed change (unless the contribution is to fix the documentation typos and mistakes).
2. Please describe the proposed api and implementation plan (unless the issue is a relatively simple bug and fixing it doesn't change any api).
3. Once agreed, please write as little code as possible to achieve the desired result.
4. Please avoid unnecessary changes, refactoring or changing coding styles as part of your change (unless the change was proposed as refactoring).
diff --git a/CUSTOM.md b/CUSTOM.md
index 6d32f40bf..68cac5ab3 100644
--- a/CUSTOM.md
+++ b/CUSTOM.md
@@ -34,26 +34,35 @@ This way to define keywords is useful for:
- testing your keywords before converting them to compiled/inlined keywords
- defining keywords that do not depend on the schema value (e.g., when the value is always `true`). In this case you can add option `schema: false` to the keyword definition and the schemas won't be passed to the validation function, it will only receive the same 4 parameters as compiled validation function (see the next section).
- defining keywords where the schema is a value used in some expression.
-- defining keywords that support [$data reference](https://github.com/epoberezkin/ajv#data-reference) - in this case validation function is required, either as the only option or in addition to compile, macro or inline function (see below).
+- defining keywords that support [$data reference](https://github.com/ajv-validator/ajv#data-reference) - in this case validation function is required, either as the only option or in addition to compile, macro or inline function (see below).
__Please note__: In cases when validation flow is different depending on the schema and you have to use `if`s, this way to define keywords will have worse performance than compiled keyword returning different validation functions depending on the schema.
-Example. `constant` keyword (a synonym for draft6 keyword `const`, it is equivalent to `enum` keyword with one item):
+Example. `constant` keyword (a synonym for draft-06 keyword `const`, it is equivalent to `enum` keyword with one item):
```javascript
-ajv.addKeyword('constant', { validate: function (schema, data) {
- return typeof schema == 'object' && schema !== null
- ? deepEqual(schema, data)
- : schema === data;
-}, errors: false });
+ajv.addKeyword('constant', {
+ validate: function (schema, data) {
+ return typeof schema == 'object' && schema !== null
+ ? deepEqual(schema, data)
+ : schema === data;
+ },
+ errors: false
+});
-var schema = { "constant": 2 };
+var schema = {
+ "constant": 2
+};
var validate = ajv.compile(schema);
console.log(validate(2)); // true
console.log(validate(3)); // false
-var schema = { "constant": { "foo": "bar" } };
+var schema = {
+ "constant": {
+ "foo": "bar"
+ }
+};
var validate = ajv.compile(schema);
console.log(validate({foo: 'bar'})); // true
console.log(validate({foo: 'baz'})); // false
@@ -79,27 +88,40 @@ The access to the parent data object and the current property name allow to crea
The function should return validation result as boolean. It can return an array of validation errors via `.errors` property of itself (otherwise a standard error will be used).
-In some cases it is the best approach to define keywords, but it has the performance cost of an extra function call during validation. If keyword logic can be expressed via some other JSON-schema then `macro` keyword definition is more efficient (see below).
+In some cases it is the best approach to define keywords, but it has the performance cost of an extra function call during validation. If keyword logic can be expressed via some other JSON Schema then `macro` keyword definition is more efficient (see below).
All custom keywords types can have an optional `metaSchema` property in their definitions. It is a schema against which the value of keyword will be validated during schema compilation.
+Custom keyword can also have an optional `dependencies` property in their definitions - it is a list of required keywords in a containing (parent) schema.
+
Example. `range` and `exclusiveRange` keywords using compiled schema:
```javascript
-ajv.addKeyword('range', { type: 'number', compile: function (sch, parentSchema) {
- var min = sch[0];
- var max = sch[1];
-
- return parentSchema.exclusiveRange === true
- ? function (data) { return data > min && data < max; }
- : function (data) { return data >= min && data <= max; }
-}, errors: false, metaSchema: {
- type: 'array',
- items: [ { type: 'number' }, { type: 'number' } ],
- additionalItems: false
-} });
+ajv.addKeyword('range', {
+ type: 'number',
+ compile: function (sch, parentSchema) {
+ var min = sch[0];
+ var max = sch[1];
+
+ return parentSchema.exclusiveRange === true
+ ? function (data) { return data > min && data < max; }
+ : function (data) { return data >= min && data <= max; }
+ },
+ errors: false,
+ metaSchema: {
+ type: 'array',
+ items: [
+ { type: 'number' },
+ { type: 'number' }
+ ],
+ additionalItems: false
+ }
+});
-var schema = { "range": [2, 4], "exclusiveRange": true };
+var schema = {
+ "range": [2, 4],
+ "exclusiveRange": true
+};
var validate = ajv.compile(schema);
console.log(validate(2.01)); // true
console.log(validate(3.99)); // true
@@ -114,7 +136,7 @@ See note on custom errors and asynchronous keywords in the previous section.
"Macro" function is called during schema compilation. It is passed schema, parent schema and [schema compilation context](#schema-compilation-context) and it should return another schema that will be applied to the data in addition to the original schema.
-It is the most efficient approach (in cases when the keyword logic can be expressed with another JSON-schema) because it is usually easy to implement and there is no extra function call during validation.
+It is the most efficient approach (in cases when the keyword logic can be expressed with another JSON Schema) because it is usually easy to implement and there is no extra function call during validation.
In addition to the errors from the expanded schema macro keyword will add its own error in case validation fails.
@@ -122,27 +144,30 @@ In addition to the errors from the expanded schema macro keyword will add its ow
Example. `range` and `exclusiveRange` keywords from the previous example defined with macro:
```javascript
-ajv.addKeyword('range', { type: 'number', macro: function (schema, parentSchema) {
- return {
- minimum: schema[0],
- maximum: schema[1],
- exclusiveMinimum: !!parentSchema.exclusiveRange,
- exclusiveMaximum: !!parentSchema.exclusiveRange
- };
-}, metaSchema: {
- type: 'array',
- items: [ { type: 'number' }, { type: 'number' } ],
- additionalItems: false
-} });
+ajv.addKeyword('range', {
+ type: 'number',
+ macro: function (schema, parentSchema) {
+ return {
+ minimum: schema[0],
+ maximum: schema[1],
+ exclusiveMinimum: !!parentSchema.exclusiveRange,
+ exclusiveMaximum: !!parentSchema.exclusiveRange
+ };
+ },
+ metaSchema: {
+ type: 'array',
+ items: [
+ { type: 'number' },
+ { type: 'number' }
+ ],
+ additionalItems: false
+ }
+});
```
Example. `contains` keyword from version 5 proposals that requires that the array has at least one item matching schema (see https://github.com/json-schema/json-schema/wiki/contains-(v5-proposal)):
```javascript
-ajv.addKeyword('contains', { type: 'array', macro: function (schema) {
- return { "not": { "items": { "not": schema } } };
-} });
-
var schema = {
"contains": {
"type": "number",
@@ -151,7 +176,20 @@ var schema = {
}
};
-var validate = ajv.compile(schema);
+var validate = ajv.addKeyword('contains', {
+ type: 'array',
+ macro: function (schema) {
+ return {
+ "not": {
+ "items": {
+ "not": schema
+ }
+ }
+ };
+ }
+})
+.compile(schema);
+
console.log(validate([1,2,3])); // false
console.log(validate([2,3,4])); // false
console.log(validate([3,4,5])); // true, number 5 matches schema inside "contains"
@@ -159,7 +197,7 @@ console.log(validate([3,4,5])); // true, number 5 matches schema inside "contain
`contains` keyword is already available in Ajv with option `v5: true`.
-See the example of defining recursive macro keyword `deepProperties` in the [test](https://github.com/epoberezkin/ajv/blob/master/spec/custom.spec.js#L151).
+See the example of defining recursive macro keyword `deepProperties` in the [test](https://github.com/ajv-validator/ajv/blob/master/spec/custom.spec.js#L151).
### Define keyword with "inline" compilation function
@@ -177,14 +215,18 @@ While it can be more challenging to define keywords with "inline" functions, it
Example `even` keyword:
```javascript
-ajv.addKeyword('even', { type: 'number', inline: function (it, keyword, schema) {
- var op = schema ? '===' : '!==';
- return 'data' + (it.dataLevel || '') + ' % 2 ' + op + ' 0';
-}, metaSchema: { type: 'boolean' } });
-
var schema = { "even": true };
-var validate = ajv.compile(schema);
+var validate = ajv.addKeyword('even', {
+ type: 'number',
+ inline: function (it, keyword, schema) {
+ var op = schema ? '===' : '!==';
+ return 'data' + (it.dataLevel || '') + ' % 2 ' + op + ' 0';
+ },
+ metaSchema: { type: 'boolean' }
+})
+.compile(schema);
+
console.log(validate(2)); // true
console.log(validate(3)); // false
```
@@ -214,7 +256,10 @@ ajv.addKeyword('range', {
statements: true,
metaSchema: {
type: 'array',
- items: [ { type: 'number' }, { type: 'number' } ],
+ items: [
+ { type: 'number' },
+ { type: 'number' }
+ ],
additionalItems: false
}
});
@@ -249,7 +294,7 @@ The first parameter passed to inline keyword compilation function (and the 3rd p
- _opts_ - Ajv instance option. You should not be changing them.
- _formats_ - all formats available in Ajv instance, including the custom ones.
- _compositeRule_ - boolean indicating that the current schema is inside the compound keyword where failing some rule doesn't mean validation failure (`anyOf`, `oneOf`, `not`, `if` in `switch`). This flag is used to determine whether you can return validation result immediately after any error in case the option `allErrors` is not `true. You only need to do it if you have many steps in your keywords and potentially can define multiple errors.
-- _validate_ - the function you need to use to compile subschemas in your keywords (see the [implementation](https://github.com/epoberezkin/ajv/blob/master/lib/dot/v5/switch.jst) of `switch` keyword for example).
+- _validate_ - the function you need to use to compile subschemas in your keywords (see the [implementation](https://github.com/ajv-validator/ajv-keywords/blob/master/keywords/dot/switch.jst) of `switch` keyword for example).
- _util_ - [Ajv utilities](#ajv-utilities) you can use in your inline compilation functions.
- _self_ - Ajv instance.
@@ -266,8 +311,8 @@ There is a number of variables and expressions you can use in the generated (val
- `'validate.schema' + it.schemaPath` - current level schema available at validation time (the same schema at compile time is `it.schema`).
- `'validate.schema' + it.schemaPath + '.' + keyword` - the value of your custom keyword at validation-time. Keyword is passed as the second parameter to the inline compilation function to allow using the same function to compile multiple keywords.
- `'valid' + it.level` - the variable that you have to declare and to assign the validation result to if your keyword returns statements rather than expression (`statements: true`).
-- `'errors'` - the number of encountered errors. See [Reporting errors in custom keywords](https://github.com/epoberezkin/ajv/blob/master/CUSTOM.md#reporting-errors-in-custom-keywords).
-- `'vErrors'` - the array with errors collected so far. See [Reporting errors in custom keywords](https://github.com/epoberezkin/ajv/blob/master/CUSTOM.md#reporting-errors-in-custom-keywords).
+- `'errors'` - the number of encountered errors. See [Reporting errors in custom keywords](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md#reporting-errors-in-custom-keywords).
+- `'vErrors'` - the array with errors collected so far. See [Reporting errors in custom keywords](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md#reporting-errors-in-custom-keywords).
## Ajv utilities
@@ -365,7 +410,7 @@ All custom keywords but macro keywords can optionally create custom error messag
Synchronous validating and compiled keywords should define errors by assigning them to `.errors` property of the validation function. Asynchronous keywords can return promise that rejects with `new Ajv.ValidationError(errors)`, where `errors` is an array of custom validation errors (if you don't want to define custom errors in asynchronous keyword, its validation function can return the promise that resolves with `false`).
-Inline custom keyword should increase error counter `errors` and add error to `vErrors` array (it can be null). This can be done for both synchronous and asynchronous keywords. See [example range keyword](https://github.com/epoberezkin/ajv/blob/master/spec/custom_rules/range_with_errors.jst).
+Inline custom keyword should increase error counter `errors` and add error to `vErrors` array (it can be null). This can be done for both synchronous and asynchronous keywords. See [example range keyword](https://github.com/ajv-validator/ajv/blob/master/spec/custom_rules/range_with_errors.jst).
When inline keyword performs validation Ajv checks whether it created errors by comparing errors count before and after validation. To skip this check add option `errors` (can be `"full"`, `true` or `false`) to keyword definition:
@@ -384,7 +429,7 @@ Each error object should at least have properties `keyword`, `message` and `para
Inlined keywords can optionally define `dataPath` and `schemaPath` properties in error objects, that will be assigned by Ajv unless `errors` option of the keyword is `"full"`.
-If custom keyword doesn't create errors, the default error will be created in case the keyword fails validation (see [Validation errors](https://github.com/epoberezkin/ajv#validation-errors)).
+If custom keyword doesn't create errors, the default error will be created in case the keyword fails validation (see [Validation errors](https://github.com/ajv-validator/ajv#validation-errors)).
## Short-circuit validation
diff --git a/FAQ.md b/FAQ.md
index 41c985a47..f010a51c8 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -3,9 +3,30 @@
The purpose of this document is to help find answers quicker. I am happy to continue the discussion about these issues, so please comment on some of the issues mentioned below or create a new issue if it seems more appropriate.
+
+## Using JSON schema
+
+Ajv implements JSON schema specification. Before submitting the issue about the behaviour of any validation keywords please review them in:
+
+- [JSON Schema specification](https://tools.ietf.org/html/draft-handrews-json-schema-validation-00) (draft-07)
+- [Validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md) in Ajv documentation
+- [JSON Schema tutorial](https://spacetelescope.github.io/understanding-json-schema/) (for draft-04)
+
+
+##### Why Ajv validates empty object as valid?
+
+"properties" keyword does not require the presence of any properties, you need to use "required" keyword. It also doesn't require that the data is an object, so any other type of data will also be valid. To require a specific type use "type" keyword.
+
+
+##### Why Ajv validates only the first item of the array?
+
+"items" keyword support [two syntaxes](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#items) - 1) when the schema applies to all items; 2) when there is a different schema for each item in the beginning of the array. This problem means you are using the second syntax.
+
+
+
## Ajv API for returning validation errors
-See [#65](https://github.com/epoberezkin/ajv/issues/65), [#212](https://github.com/epoberezkin/ajv/issues/212), [#236](https://github.com/epoberezkin/ajv/issues/236), [#242](https://github.com/epoberezkin/ajv/issues/242), [#256](https://github.com/epoberezkin/ajv/issues/256).
+See [#65](https://github.com/ajv-validator/ajv/issues/65), [#212](https://github.com/ajv-validator/ajv/issues/212), [#236](https://github.com/ajv-validator/ajv/issues/236), [#242](https://github.com/ajv-validator/ajv/issues/242), [#256](https://github.com/ajv-validator/ajv/issues/256).
##### Why Ajv assigns errors as a property of validation function (or instance) instead of returning an object with validation results and errors?
@@ -29,17 +50,18 @@ No. In many cases there is a module responsible for the validation in the applic
Doing this would create a precedent where validated data is used in error messages, creating a vulnerability (e.g., when ajv is used to validate API data/parameters and error messages are logged).
-Since the property name is already in the params object, in an application you can modify messages in any way you need. ajv-errors package will allow to modify messages as well - templating is [not there yet](https://github.com/epoberezkin/ajv-errors/issues/4), though.
+Since the property name is already in the params object, in an application you can modify messages in any way you need. ajv-errors package allows modifying messages as well.
+
## Additional properties inside compound keywords anyOf, oneOf, etc.
-See [#127](https://github.com/epoberezkin/ajv/issues/127), [#129](https://github.com/epoberezkin/ajv/issues/129), [#134](https://github.com/epoberezkin/ajv/issues/134), [#140](https://github.com/epoberezkin/ajv/issues/140), [#193](https://github.com/epoberezkin/ajv/issues/193), [#205](https://github.com/epoberezkin/ajv/issues/205), [#238](https://github.com/epoberezkin/ajv/issues/238), [#264](https://github.com/epoberezkin/ajv/issues/264).
+See [#127](https://github.com/ajv-validator/ajv/issues/127), [#129](https://github.com/ajv-validator/ajv/issues/129), [#134](https://github.com/ajv-validator/ajv/issues/134), [#140](https://github.com/ajv-validator/ajv/issues/140), [#193](https://github.com/ajv-validator/ajv/issues/193), [#205](https://github.com/ajv-validator/ajv/issues/205), [#238](https://github.com/ajv-validator/ajv/issues/238), [#264](https://github.com/ajv-validator/ajv/issues/264).
##### Why the keyword `additionalProperties: false` fails validation when some properties are "declared" inside a subschema in `anyOf`/etc.?
-The keyword `additionalProperties` creates the restriction on validated data based on its own value (`false` or schema object) and on the keywords `properties` and `patternProperties` in the SAME schema object. JSON-schema validators must NOT take into account properties used in other schema objects.
+The keyword `additionalProperties` creates the restriction on validated data based on its own value (`false` or schema object) and on the keywords `properties` and `patternProperties` in the SAME schema object. JSON Schema validators must NOT take into account properties used in other schema objects.
While you can expect that the schema below would allow the objects either with properties `foo` and `bar` or with properties `foo` and `baz` and all other properties will be prohibited, this schema will only allow objects with one property `foo` (an empty object and any non-objects will also be valid):
@@ -61,14 +83,15 @@ There are several ways to implement the described logic that would allow two pro
##### Why the validation fails when I use option `removeAdditional` with the keyword `anyOf`/etc.?
-This problem is related to the problem explained above - properties treated as additional in the sence of `additionalProperties` keyword, based on `properties`/`patternProperties` keyword in the same schema object.
+This problem is related to the problem explained above - properties treated as additional in the sense of `additionalProperties` keyword, based on `properties`/`patternProperties` keyword in the same schema object.
+
+See the exemple in [Filtering Data](https://github.com/ajv-validator/ajv#filtering-data) section of readme.
-See the exemple in [Filtering Data](https://github.com/epoberezkin/ajv#filtering-data) section of readme.
## Generating schemas with resolved references ($ref)
-See [#22](https://github.com/epoberezkin/ajv/issues/22), [#125](https://github.com/epoberezkin/ajv/issues/125), [#146](https://github.com/epoberezkin/ajv/issues/146), [#228](https://github.com/epoberezkin/ajv/issues/228), [#336](https://github.com/epoberezkin/ajv/issues/336), [#454](https://github.com/epoberezkin/ajv/issues/454).
+See [#22](https://github.com/ajv-validator/ajv/issues/22), [#125](https://github.com/ajv-validator/ajv/issues/125), [#146](https://github.com/ajv-validator/ajv/issues/146), [#228](https://github.com/ajv-validator/ajv/issues/228), [#336](https://github.com/ajv-validator/ajv/issues/336), [#454](https://github.com/ajv-validator/ajv/issues/454).
##### Why Ajv does not replace references ($ref) with the actual referenced schemas as some validators do?
@@ -77,12 +100,12 @@ See [#22](https://github.com/epoberezkin/ajv/issues/22), [#125](https://github.c
2. When schemas are recursive (or mutually recursive) resolving references would result in self-referencing recursive data-structures that can be difficult to process.
3. There are cases when such inlining would also require adding (or modyfing) `id` attribute in the inlined schema fragment to make the resulting schema equivalent.
-There were many conversations about the meaning of `$ref` in [JSON Schema GitHub organisation](https://github.com/json-schema-org). The consesus is that while it is possible to treat `$ref` as schema inclusion with two caveats (above), this interpretation is unnecessary complex. A more efficient approach is to treat `$ref` as a delegation, i.e. a special keyword that validates the current data instance against the referenced schema. The analogy with programming languages is that `$ref` is a function call rather than a macro. See [here](https://github.com/json-schema-org/json-schema-spec/issues/279), for example.
+There were many conversations about the meaning of `$ref` in [JSON Schema GitHub organisation](https://github.com/json-schema-org). The consensus is that while it is possible to treat `$ref` as schema inclusion with two caveats (above), this interpretation is unnecessary complex. A more efficient approach is to treat `$ref` as a delegation, i.e. a special keyword that validates the current data instance against the referenced schema. The analogy with programming languages is that `$ref` is a function call rather than a macro. See [here](https://github.com/json-schema-org/json-schema-spec/issues/279), for example.
##### How can I generate a schema where `$ref` keywords are replaced with referenced schemas?
There are two possible approaches:
-1. Write code to traverse schema and replace every `$ref` with the referenced schema. An additional limitation is that `"$ref"` inside keywords "properties", "patternProperties" and "dependencies" means property name (or pattern) rather than the reference to another schema.
-2. Use a specially constructed JSON Schema with a [custom keyword](https://github.com/epoberezkin/ajv/blob/master/CUSTOM.md) to traverse and modify your schema.
+1. Traverse schema (e.g. with json-schema-traverse) and replace every `$ref` with the referenced schema.
+2. Use a specially constructed JSON Schema with a [custom keyword](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md) to traverse and modify your schema.
diff --git a/KEYWORDS.md b/KEYWORDS.md
index c53e15e95..6601a9a1b 100644
--- a/KEYWORDS.md
+++ b/KEYWORDS.md
@@ -1,7 +1,7 @@
# JSON Schema validation keywords
-In a simple way, JSON schema is an object with validation keywords.
+In a simple way, JSON Schema is an object with validation keywords.
The keywords and their values define what rules the data should satisfy to be valid.
@@ -10,7 +10,7 @@ The keywords and their values define what rules the data should satisfy to be va
- [type](#type)
- [Keywords for numbers](#keywords-for-numbers)
- - [maximum / minimum and exclusiveMaximum / exclusiveMinimum](#maximum--minimum-and-exclusivemaximum--exclusiveminimum) (CHANGED in draft 6)
+ - [maximum / minimum and exclusiveMaximum / exclusiveMinimum](#maximum--minimum-and-exclusivemaximum--exclusiveminimum) (changed in draft-06)
- [multipleOf](#multipleof)
- [Keywords for strings](#keywords-for-strings)
- [maxLength/minLength](#maxlength--minlength)
@@ -22,7 +22,7 @@ The keywords and their values define what rules the data should satisfy to be va
- [uniqueItems](#uniqueitems)
- [items](#items)
- [additionalItems](#additionalitems)
- - [contains](#contains) (NEW in draft 6)
+ - [contains](#contains) (added in draft-06)
- [Keywords for objects](#keywords-for-objects)
- [maxProperties/minProperties](#maxproperties--minproperties)
- [required](#required)
@@ -30,18 +30,17 @@ The keywords and their values define what rules the data should satisfy to be va
- [patternProperties](#patternproperties)
- [additionalProperties](#additionalproperties)
- [dependencies](#dependencies)
- - [propertyNames](#propertynames) (NEW in draft 6)
- - [patternGroups](#patterngroups-deprecated) (deprecated)
+ - [propertyNames](#propertynames) (added in draft-06)
- [patternRequired](#patternrequired-proposed) (proposed)
- [Keywords for all types](#keywords-for-all-types)
- [enum](#enum)
- - [const](#const) (NEW in draft 6)
+ - [const](#const) (added in draft-06)
- [Compound keywords](#compound-keywords)
- [not](#not)
- [oneOf](#oneof)
- [anyOf](#anyof)
- [allOf](#allof)
- - [switch](#switch-proposed) (proposed)
+ - [if/then/else](#ifthenelse) (NEW in draft-07)
@@ -49,7 +48,7 @@ The keywords and their values define what rules the data should satisfy to be va
`type` keyword requires that the data is of certain type (or some of types). Its value can be a string (the allowed type) or an array of strings (multiple allowed types).
-Type can be: number, integer, string, boolean, array, object or null.
+Type can be: `number`, `integer`, `string`, `boolean`, `array`, `object` or `null`.
__Examples__
@@ -75,7 +74,7 @@ __Examples__
_invalid_: `[]`, `{}`, `null`, `true`
-All examples above are JSON schemas that only require data to be of certain type to be valid.
+All examples above are JSON Schemas that only require data to be of certain type to be valid.
Most other keywords apply only to a particular type of data. If the data is of different type, the keyword will not apply and the data will be considered valid.
@@ -88,11 +87,11 @@ Most other keywords apply only to a particular type of data. If the data is of d
The value of keyword `maximum` (`minimum`) should be a number. This value is the maximum (minimum) allowed value for the data to be valid.
-Draft 4: The value of keyword `exclusiveMaximum` (`exclusiveMinimum`) should be a boolean value. These keyword cannot be used without `maximum` (`minimum`). If this keyword value is equal to `true`, the data should not be equal to the value in `maximum` (`minimum`) keyword to be valid.
+Draft-04: The value of keyword `exclusiveMaximum` (`exclusiveMinimum`) should be a boolean value. These keyword cannot be used without `maximum` (`minimum`). If this keyword value is equal to `true`, the data should not be equal to the value in `maximum` (`minimum`) keyword to be valid.
-Draft 6: The value of keyword `exclusiveMaximum` (`exclusiveMinimum`) should be a number. This value is the exclusive maximum (minimum) allowed value for the data to be valid (the data equal to this keyword value is invalid).
+Draft-06/07: The value of keyword `exclusiveMaximum` (`exclusiveMinimum`) should be a number. This value is the exclusive maximum (minimum) allowed value for the data to be valid (the data equal to this keyword value is invalid).
-Ajv supports both draft 4 and draft 6 syntaxes.
+Ajv supports both draft-04 and draft-06/07 syntaxes.
__Examples__
@@ -112,8 +111,8 @@ __Examples__
3. _schema_:
- draft 4: `{ "minimum": 5, "exclusiveMinimum": true }`
- draft 6: `{ "exclusiveMinimum": 5 }`
+ draft-04: `{ "minimum": 5, "exclusiveMinimum": true }`
+ draft-06/07: `{ "exclusiveMinimum": 5 }`
_valid_: `6`, `7`, any non-number (`"abc"`, `[]`, `{}`, `null`, `true`)
@@ -203,7 +202,7 @@ _invalid_: `"abc"`
### `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum` (proposed)
-Defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package.
+Defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package.
The value of keyword `formatMaximum` (`formatMinimum`) should be a string. This value is the maximum (minimum) allowed value for the data to be valid as determined by `format` keyword.
@@ -268,7 +267,7 @@ The value of the keyword should be an object or an array of objects.
If the keyword value is an object, then for the data array to be valid each item of the array should be valid according to the schema in this value. In this case the "additionalItems" keyword is ignored.
-If the keyword value is an array, then items with indeces less than the number of items in the keyword should be valid according to the schemas with the same indeces. Whether additional items are valid will depend on "additionalItems" keyword.
+If the keyword value is an array, then items with indices less than the number of items in the keyword should be valid according to the schemas with the same indices. Whether additional items are valid will depend on "additionalItems" keyword.
__Examples__
@@ -308,7 +307,7 @@ If the length of data array is bigger than the length of "items" keyword value t
- `false`: data is invalid
- `true`: data is valid
-- an object: data is valid if all additional items (i.e. items with indeces greater or equal than "items" keyword value length) are valid according to the schema in "assitionalItems" keyword.
+- an object: data is valid if all additional items (i.e. items with indices greater or equal than "items" keyword value length) are valid according to the schema in "additionalItems" keyword.
__Examples__
@@ -365,7 +364,7 @@ __Examples__
### `contains`
-The value of the keyword is a JSON-schema. The array is valid if it contains at least one item that is valid according to this schema.
+The value of the keyword is a JSON Schema. The array is valid if it contains at least one item that is valid according to this schema.
__Example__
@@ -424,7 +423,7 @@ _invalid_: `{}`, `{"a": 1}`, `{"c": 3, "d":4}`
### `properties`
-The value of the keyword should be a map with keys equal to data object properties. Each value in the map should be a JSON schema. For data object to be valid the corresponding values in data object properties should be valid according to these schemas.
+The value of the keyword should be a map with keys equal to data object properties. Each value in the map should be a JSON Schema. For data object to be valid the corresponding values in data object properties should be valid according to these schemas.
__Please note__: `properties` keyword does not require that the properties mentioned in it are present in the object (see examples).
@@ -451,7 +450,7 @@ _invalid_: `{"foo": 1}`, `{"foo": "a", "bar": 1}`
### `patternProperties`
-The value of this keyword should be a map where keys should be regular expressions and the values should be JSON schemas. 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).
+The value of this keyword should be a map where keys should be regular expressions and the values should be JSON Schemas. 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).
When the value in data object property matches multiple regular expressions it should be valid according to all the schemas for all matched regular expressions.
@@ -478,7 +477,7 @@ _invalid_: `{"foo": 1}`, `{"foo": "a", "bar": "b"}`
### `additionalProperties`
-The value of the keyword should be either a boolean or a JSON schema.
+The value of the keyword should be either a boolean or a JSON Schema.
If the value is `true` the keyword is ignored.
@@ -552,7 +551,7 @@ __Examples__
### `dependencies`
-The value of the keyword is a map with keys equal to data object properties. Each value in the map should be either an array of unique property names ("property dependency") or a JSON schema ("schema dependency").
+The value of the keyword is a map with keys equal to data object properties. Each value in the map should be either an array of unique property names ("property dependency") or a JSON Schema ("schema dependency").
For property dependency, if the data object contains a property that is a key in the keyword value, then to be valid the data object should also contain all properties from the array of properties.
@@ -596,7 +595,7 @@ __Examples__
### `propertyNames`
-The value of this keyword is a JSON schema.
+The value of this keyword is a JSON Schema.
For data object to be valid each property name in this object should be valid according to this schema.
@@ -617,44 +616,9 @@ _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.
+Defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package.
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.
@@ -706,7 +670,7 @@ _valid_: `"foo"`
_invalid_: any other value
-The same can be achieved with `enum` keyword using the array with one item. But `const` keyword is more than just a syntax sugar for `enum`. In combination with the [$data reference](https://github.com/epoberezkin/ajv#data-reference) it allows to define equality relations between different parts of the data. This cannot be achieved with `enum` keyword even with `$data` reference because `$data` cannot be used in place of one item - it can only be used in place of the whole array in `enum` keyword.
+The same can be achieved with `enum` keyword using the array with one item. But `const` keyword is more than just a syntax sugar for `enum`. In combination with the [$data reference](https://github.com/ajv-validator/ajv#data-reference) it allows to define equality relations between different parts of the data. This cannot be achieved with `enum` keyword even with `$data` reference because `$data` cannot be used in place of one item - it can only be used in place of the whole array in `enum` keyword.
__Example__
@@ -732,7 +696,7 @@ _invalid_: `{ "foo": 1 }`, `{ "bar": 1 }`, `{ "foo": 1, "bar": 2 }`
### `not`
-The value of the keyword should be a JSON schema. The data is valid if it is invalid according to this schema.
+The value of the keyword should be a JSON Schema. The data is valid if it is invalid according to this schema.
__Examples__
@@ -763,7 +727,7 @@ __Examples__
### `oneOf`
-The value of the keyword should be an array of JSON schemas. The data is valid if it matches exactly one JSON schema from this array. Validators have to validate data against all schemas to establish validity according to this keyword.
+The value of the keyword should be an array of JSON Schemas. The data is valid if it matches exactly one JSON Schema from this array. Validators have to validate data against all schemas to establish validity according to this keyword.
__Example__
@@ -786,7 +750,7 @@ _invalid_: `2`, `3`, `4.5`, `5.5`
### `anyOf`
-The value of the keyword should be an array of JSON schemas. The data is valid if it is valid according to one or more JSON schemas in this array. Validators only need to validate data against schemas in order until the first schema matches (or until all schemas have been tried). For this reason validating against this keyword is faster than against "oneOf" keyword in most cases.
+The value of the keyword should be an array of JSON Schemas. The data is valid if it is valid according to one or more JSON Schemas in this array. Validators only need to validate data against schemas in order until the first schema matches (or until all schemas have been tried). For this reason validating against this keyword is faster than against "oneOf" keyword in most cases.
__Example__
@@ -809,7 +773,7 @@ _invalid_: `4.5`, `5.5`
### `allOf`
-The value of the keyword should be an array of JSON schemas. The data is valid if it is valid according to all JSON schemas in this array.
+The value of the keyword should be an array of JSON Schemas. The data is valid if it is valid according to all JSON Schemas in this array.
__Example__
@@ -830,29 +794,15 @@ _invalid_: `1.5`, `2.5`, `4`, `4.5`, `5`, `5.5`, any non-number
-### `switch` (proposed)
-
-Defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package.
+### `if`/`then`/`else`
-The value of the keyword is the array of if/then clauses. Each clause is the object with the following properties:
+These keywords allow to implement conditional validation. Their values should be valid JSON Schemas (object or boolean).
-- `if` (optional) - the value is JSON-schema
-- `then` (required) - the value is JSON-schema or boolean
-- `continue` (optional) - the value is boolean
+If `if` keyword is absent, the validation succeds.
-The validation process is dynamic; all clauses are executed sequentially in the following way:
+If the data is valid against the sub-schema in `if` keyword, then the validation result is equal to the result of data validation against the sub-schema in `then` keyword (if `then` is absent, the validation succeeds).
-1. `if`:
- 1. `if` property is JSON-schema according to which the data is:
- 1. valid => go to step 2.
- 2. invalid => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
- 2. `if` property is absent => go to step 2.
-2. `then`:
- 1. `then` property is `true` or it is JSON-schema according to which the data is valid => go to step 3.
- 2. `then` property is `false` or it is JSON-schema according to which the data is invalid => the validation of `switch` FAILS.
-3. `continue`:
- 1. `continue` property is `true` => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
- 2. `continue` property is `false` or absent => validation of `switch` SUCCEEDS.
+If the data is invalid against the sub-schema in `if` keyword, then the validation result is equal to the result of data validation against the sub-schema in `else` keyword (if `else` is absent, the validation succeeds).
__Examples__
@@ -861,29 +811,24 @@ __Examples__
```json
{
- "switch": [
- {
- "if": { "properties": { "power": { "minimum": 9000 } } },
- "then": { "required": [ "disbelief" ] },
- "continue": true
- },
- { "then": { "required": [ "confidence" ] } }
- ]
+ "if": { "properties": { "power": { "minimum": 9000 } } },
+ "then": { "required": [ "disbelief" ] },
+ "else": { "required": [ "confidence" ] }
}
```
_valid_:
- - `{ "power": 9000, "disbelief": true, "confidence": true }`
- - `{ "confidence": true }`
+ - `{ "power": 10000, "disbelief": true }`
+ - `{}`
- `{ "power": 1000, "confidence": true }`
+ - any non-object
_invalid_:
- - `{ "power": 9000 }` (`disbelief` & `confidence` are required)
- - `{ "power": 9000, "disbelief": true }` (`confidence` is always required)
- - `{ "power": 1000 }`
- - `{}`
+ - `{ "power": 10000 }` (`disbelief` is required)
+ - `{ "power": 10000, "confidence": true }` (`disbelief` is required)
+ - `{ "power": 1000 }` (`confidence` is required)
2. _schema_:
@@ -891,13 +836,14 @@ __Examples__
```json
{
"type": "integer",
- "switch": [
- { "if": { "not": { "minimum": 1 } }, "then": false },
- { "if": { "maximum": 10 }, "then": true },
- { "if": { "maximum": 100 }, "then": { "multipleOf": 10 } },
- { "if": { "maximum": 1000 }, "then": { "multipleOf": 100 } },
- { "then": false }
- ]
+ "minimum": 1,
+ "maximum": 1000,
+ "if": { "minimum": 100 },
+ "then": { "multipleOf": 100 },
+ "else": {
+ "if": { "minimum": 10 },
+ "then": { "multipleOf": 10 }
+ }
}
```
diff --git a/LICENSE b/LICENSE
index 810539685..96ee71998 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2015 Evgeny Poberezkin
+Copyright (c) 2015-2017 Evgeny Poberezkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 62a52516a..5e502db93 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,76 @@
-
+
# Ajv: Another JSON Schema Validator
-The fastest JSON Schema validator for Node.js and browser with draft 6 support.
+The fastest JSON Schema validator for Node.js and browser. Supports draft-04/06/07.
-
-[](https://travis-ci.org/epoberezkin/ajv)
-[](https://www.npmjs.com/package/ajv)
+[](https://travis-ci.org/ajv-validator/ajv)
+[](https://www.npmjs.com/package/ajv)
[](https://www.npmjs.com/package/ajv)
-[](https://codeclimate.com/github/epoberezkin/ajv)
-[](https://coveralls.io/github/epoberezkin/ajv?branch=master)
-[](https://greenkeeper.io/)
+[](https://coveralls.io/github/ajv-validator/ajv?branch=master)
[](https://gitter.im/ajv-validator/ajv)
+[](https://github.com/sponsors/epoberezkin)
+
+
+## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)
+
+I will get straight to the point - I need your support to ensure that the development of Ajv continues.
+
+I have developed Ajv for 5 years in my free time, but it is not sustainable. I'd appreciate if you consider supporting its further development with donations:
+- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)
+- [Ajv Open Collective️](https://opencollective.com/ajv)
+
+There are many small and large improvements that are long due, including the support of the next versions of JSON Schema specification, improving website and documentation, and making Ajv more modular and maintainable to address its limitations - what Ajv needs to evolve is much more than what I can contribute in my free time.
+
+I would also really appreciate any advice you could give on how to raise funds for Ajv development - whether some suitable open-source fund I could apply to or some sponsor I should approach.
+
+Since 2015 Ajv has become widely used, thanks to your help and contributions:
+
+- **90** contributors 🏗
+- **5,000** dependent npm packages ⚙️
+- **7,000** github stars, from GitHub users [all over the world](https://www.google.com/maps/d/u/0/viewer?mid=1MGRV8ciFUGIbO1l0EKFWNJGYE7iSkDxP&ll=-3.81666561775622e-14%2C4.821737100000007&z=2) ⭐️
+- **5,000,000** dependent repositories on GitHub 🚀
+- **120,000,000** npm downloads per month! 💯
+
+I believe it would benefit all Ajv users to help put together the fund that will be used for its further development - it would allow to bring some additional maintainers to the project.
+
+Thank you
+
+
+#### Open Collective sponsors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Using version 6
-## Using version 5
+[JSON Schema draft-07](http://json-schema.org/latest/json-schema-validation.html) is published.
-[JSON Schema draft-06](https://trac.tools.ietf.org/html/draft-wright-json-schema-validation-01) is published.
+[Ajv version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0) that supports draft-07 is released. It may require either migrating your schemas or updating your code (to continue using draft-04 and v5 schemas, draft-06 schemas will be supported without changes).
-[Ajv version 5.0.0](https://github.com/epoberezkin/ajv/releases/tag/5.0.0) that supports draft-06 is released. It may require either migrating your schemas or updating your code (to continue using draft-04 and v5 schemas).
+__Please note__: To use Ajv with draft-06 schemas you need to explicitly add the meta-schema to the validator instance:
-__Please note__: To use Ajv with draft-04 schemas you need to explicitly add meta-schema to the validator instance:
+```javascript
+ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
+```
+
+To use Ajv with draft-04 schemas in addition to explicitly adding meta-schema you also need to use option schemaId:
```javascript
+var ajv = new Ajv({schemaId: 'id'});
+// If you want to use both draft-04 and draft-06/07 schemas:
+// var ajv = new Ajv({schemaId: 'auto'});
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
```
@@ -32,11 +80,13 @@ ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
- [Performance](#performance)
- [Features](#features)
- [Getting started](#getting-started)
-- [Frequently Asked Questions](https://github.com/epoberezkin/ajv/blob/master/FAQ.md)
+- [Frequently Asked Questions](https://github.com/ajv-validator/ajv/blob/master/FAQ.md)
- [Using in browser](#using-in-browser)
+ - [Ajv and Content Security Policies (CSP)](#ajv-and-content-security-policies-csp)
- [Command line interface](#command-line-interface)
- Validation
- [Keywords](#validation-keywords)
+ - [Annotation keywords](#annotation-keywords)
- [Formats](#formats)
- [Combining schemas with $ref](#ref)
- [$data reference](#data-reference)
@@ -44,6 +94,12 @@ ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
- [Defining custom keywords](#defining-custom-keywords)
- [Asynchronous schema compilation](#asynchronous-schema-compilation)
- [Asynchronous validation](#asynchronous-validation)
+- [Security considerations](#security-considerations)
+ - [Security contact](#security-contact)
+ - [Untrusted schemas](#untrusted-schemas)
+ - [Circular references in objects](#circular-references-in-javascript-objects)
+ - [Trusted schemas](#security-risks-of-trusted-schemas)
+ - [ReDoS attack](#redos-attack)
- Modifying data during validation
- [Filtering data](#filtering-data)
- [Assigning defaults](#assigning-defaults)
@@ -52,14 +108,16 @@ ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
- [Methods](#api)
- [Options](#options)
- [Validation errors](#validation-errors)
+- [Plugins](#plugins)
- [Related packages](#related-packages)
-- [Packages using Ajv](#some-packages-using-ajv)
-- [Tests, Contributing, History, License](#tests)
+- [Some packages using Ajv](#some-packages-using-ajv)
+- [Tests, Contributing, Changes history](#tests)
+- [Support, Code of conduct, License](#open-source-software-support)
## Performance
-Ajv generates code using [doT templates](https://github.com/olado/doT) to turn JSON schemas into super-fast validation functions that are efficient for v8 optimization.
+Ajv generates code using [doT templates](https://github.com/olado/doT) to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.
Currently Ajv is the fastest and the most standard compliant validator according to these benchmarks:
@@ -71,30 +129,30 @@ Currently Ajv is the fastest and the most standard compliant validator according
Performance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):
-[](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)
+[](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)
## Features
-- Ajv implements full JSON Schema [draft 6](http://json-schema.org/) and draft 4 standards:
- - all validation keywords (see [JSON Schema validation keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md))
+- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) and draft-04 standards:
+ - all validation keywords (see [JSON Schema validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md))
- full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)
- support of circular references between schemas
- correct string lengths for strings with unicode pairs (can be turned off)
- - [formats](#formats) defined by JSON Schema draft 4 standard and custom formats (can be turned off)
+ - [formats](#formats) defined by JSON Schema draft-07 standard and custom formats (can be turned off)
- [validates schemas against meta-schema](#api-validateschema)
-- supports [browsers](#using-in-browser) and Node.js 0.10-8.x
+- supports [browsers](#using-in-browser) and Node.js 0.10-14.x
- [asynchronous loading](#asynchronous-schema-compilation) of referenced schemas during compilation
- "All errors" validation mode with [option allErrors](#options)
- [error messages with parameters](#validation-errors) describing error reasons to allow creating custom error messages
-- i18n error messages support with [ajv-i18n](https://github.com/epoberezkin/ajv-i18n) package
+- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package
- [filtering data](#filtering-data) from additional properties
- [assigning defaults](#assigning-defaults) to missing properties and items
- [coercing data](#coercing-data-types) to the types specified in `type` keywords
- [custom keywords](#defining-custom-keywords)
-- draft-6 keywords `const`, `contains` and `propertyNames`
-- draft-6 boolean schemas (`true`/`false` as a schema to always pass/fail).
-- keywords `switch`, `patternRequired`, `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum` from [JSON-schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) with [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package
+- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`
+- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).
+- keywords `switch`, `patternRequired`, `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum` from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package
- [$data reference](#data-reference) to use values from the validated data as values for the schema keywords
- [asynchronous validation](#asynchronous-validation) of custom formats and keywords
@@ -116,7 +174,11 @@ Try it in the Node.js REPL: https://tonicdev.com/npm/ajv
The fastest validation call:
```javascript
+// Node.js require:
var Ajv = require('ajv');
+// or ESM/TypeScript import
+import Ajv from 'ajv';
+
var ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
var validate = ajv.compile(schema);
var valid = validate(data);
@@ -136,20 +198,24 @@ or
```javascript
// ...
-ajv.addSchema(schema, 'mySchema');
-var valid = ajv.validate('mySchema', data);
+var valid = ajv.addSchema(schema, 'mySchema')
+ .validate('mySchema', data);
if (!valid) console.log(ajv.errorsText());
// ...
```
See [API](#api) and [Options](#options) for more details.
-Ajv compiles schemas to functions and caches them in all cases (using schema serialized with [json-stable-stringify](https://github.com/substack/json-stable-stringify) or a custom function as a key), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.
+Ajv compiles schemas to functions and caches them in all cases (using schema serialized with [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) or a custom function as a key), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.
The best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).
__Please note__: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](#validation-errors)
+__Note for TypeScript users__: `ajv` provides its own TypeScript declarations
+out of the box, so you don't need to install the deprecated `@types/ajv`
+module.
+
## Using in browser
@@ -170,56 +236,85 @@ Ajv is tested with these browsers:
[](https://saucelabs.com/u/epoberezkin)
-__Please note__: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/epoberezkin/ajv/issues/234)).
+__Please note__: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).
+
+
+### Ajv and Content Security Policies (CSP)
+
+If you're using Ajv to compile a schema (the typical use) in a browser document that is loaded with a Content Security Policy (CSP), that policy will require a `script-src` directive that includes the value `'unsafe-eval'`.
+:warning: NOTE, however, that `unsafe-eval` is NOT recommended in a secure CSP[[1]](https://developer.chrome.com/extensions/contentSecurityPolicy#relaxing-eval), as it has the potential to open the document to cross-site scripting (XSS) attacks.
+
+In order to make use of Ajv without easing your CSP, you can [pre-compile a schema using the CLI](https://github.com/ajv-validator/ajv-cli#compile-schemas). This will transpile the schema JSON into a JavaScript file that exports a `validate` function that works simlarly to a schema compiled at runtime.
+
+Note that pre-compilation of schemas is performed using [ajv-pack](https://github.com/ajv-validator/ajv-pack) and there are [some limitations to the schema features it can compile](https://github.com/ajv-validator/ajv-pack#limitations). A successfully pre-compiled schema is equivalent to the same schema compiled at runtime.
## Command line interface
-CLI is available as a separate npm package [ajv-cli](https://github.com/jessedc/ajv-cli). It supports:
+CLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:
-- compiling JSON-schemas to test their validity
-- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/epoberezkin/ajv-pack))
-- migrate schemas to draft-06 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))
-- validating data file(s) against JSON-schema
-- testing expected validity of data against JSON-schema
+- compiling JSON Schemas to test their validity
+- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))
+- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))
+- validating data file(s) against JSON Schema
+- testing expected validity of data against JSON Schema
- referenced schemas
- custom meta-schemas
-- files in JSON and JavaScript format
+- files in JSON, JSON5, YAML, and JavaScript format
- all Ajv options
- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format
## Validation keywords
-Ajv supports all validation keywords from draft 4 of JSON-schema standard:
+Ajv supports all validation keywords from draft-07 of JSON Schema standard:
+
+- [type](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#type)
+- [for numbers](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-numbers) - maximum, minimum, exclusiveMaximum, exclusiveMinimum, multipleOf
+- [for strings](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-strings) - maxLength, minLength, pattern, format
+- [for arrays](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-arrays) - maxItems, minItems, uniqueItems, items, additionalItems, [contains](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#contains)
+- [for objects](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-objects) - maxProperties, minProperties, required, properties, patternProperties, additionalProperties, dependencies, [propertyNames](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#propertynames)
+- [for all types](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-all-types) - enum, [const](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#const)
+- [compound keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#compound-keywords) - not, oneOf, anyOf, allOf, [if/then/else](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#ifthenelse)
+
+With [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package Ajv also supports validation keywords from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) for JSON Schema standard:
-- [type](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#type)
-- [for numbers](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#keywords-for-numbers) - maximum, minimum, exclusiveMaximum, exclusiveMinimum, multipleOf
-- [for strings](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#keywords-for-strings) - maxLength, minLength, pattern, format
-- [for arrays](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#keywords-for-arrays) - maxItems, minItems, uniqueItems, items, additionalItems, [contains](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#contains)
-- [for objects](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#keywords-for-objects) - maxProperties, minProperties, required, properties, patternProperties, additionalProperties, dependencies, [propertyNames](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#propertynames)
-- [for all types](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#keywords-for-all-types) - enum, [const](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#const)
-- [compound keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#compound-keywords) - not, oneOf, anyOf, allOf
+- [patternRequired](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#patternrequired-proposed) - like `required` but with patterns that some property should match.
+- [formatMaximum, formatMinimum, formatExclusiveMaximum, formatExclusiveMinimum](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#formatmaximum--formatminimum-and-exclusiveformatmaximum--exclusiveformatminimum-proposed) - setting limits for date, time, etc.
-With [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package Ajv also supports validation keywords from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) for JSON-schema standard:
+See [JSON Schema validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md) for more details.
-- [switch](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#switch-proposed) - conditional validation with a sequence of if/then clauses
-- [patternRequired](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#patternrequired-proposed) - like `required` but with patterns that some property should match.
-- [formatMaximum, formatMinimum, formatExclusiveMaximum, formatExclusiveMinimum](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#formatmaximum--formatminimum-and-exclusiveformatmaximum--exclusiveformatminimum-proposed) - setting limits for date, time, etc.
-See [JSON Schema validation keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md) for more details.
+## Annotation keywords
+
+JSON Schema specification defines several annotation keywords that describe schema itself but do not perform any validation.
+
+- `title` and `description`: information about the data represented by that schema
+- `$comment` (NEW in draft-07): information for developers. With option `$comment` Ajv logs or passes the comment string to the user-supplied function. See [Options](#options).
+- `default`: a default value of the data instance, see [Assigning defaults](#assigning-defaults).
+- `examples` (NEW in draft-06): an array of data instances. Ajv does not check the validity of these instances against the schema.
+- `readOnly` and `writeOnly` (NEW in draft-07): marks data-instance as read-only or write-only in relation to the source of the data (database, api, etc.).
+- `contentEncoding`: [RFC 2045](https://tools.ietf.org/html/rfc2045#section-6.1 ), e.g., "base64".
+- `contentMediaType`: [RFC 2046](https://tools.ietf.org/html/rfc2046), e.g., "image/png".
+
+__Please note__: Ajv does not implement validation of the keywords `examples`, `contentEncoding` and `contentMediaType` but it reserves them. If you want to create a plugin that implements some of them, it should remove these keywords from the instance.
## Formats
-The following formats are supported for string validation with "format" keyword:
+Ajv implements formats defined by JSON Schema specification and several other formats. It is recommended NOT to use "format" keyword implementations with untrusted data, as they use potentially unsafe regular expressions - see [ReDoS attack](#redos-attack).
+
+__Please note__: if you need to use "format" keyword to validate untrusted data, you MUST assess their suitability and safety for your validation scenarios.
+
+The following formats are implemented for string validation with "format" keyword:
- _date_: full-date according to [RFC3339](http://tools.ietf.org/html/rfc3339#section-5.6).
- _time_: time with optional time-zone.
- _date-time_: date-time from the same source (time-zone is mandatory). `date`, `time` and `date-time` validate ranges in `full` mode and only regexp in `fast` mode (see [options](#options)).
-- _uri_: full uri with optional protocol.
-- _url_: [URL record](https://url.spec.whatwg.org/#concept-url).
+- _uri_: full URI.
+- _uri-reference_: URI reference, including full and relative URIs.
- _uri-template_: URI template according to [RFC6570](https://tools.ietf.org/html/rfc6570)
+- _url_ (deprecated): [URL record](https://url.spec.whatwg.org/#concept-url).
- _email_: email address.
- _hostname_: host name according to [RFC1034](http://tools.ietf.org/html/rfc1034#section-3.5).
- _ipv4_: IP address v4.
@@ -229,13 +324,15 @@ The following formats are supported for string validation with "format" keyword:
- _json-pointer_: JSON-pointer according to [RFC6901](https://tools.ietf.org/html/rfc6901).
- _relative-json-pointer_: relative JSON-pointer according to [this draft](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00).
-There are two modes of format validation: `fast` and `full`. This mode affects formats `date`, `time`, `date-time`, `uri`, `email`, and `hostname`. See [Options](#options) for details.
+__Please note__: JSON Schema draft-07 also defines formats `iri`, `iri-reference`, `idn-hostname` and `idn-email` for URLs, hostnames and emails with international characters. Ajv does not implement these formats. If you create Ajv plugin that implements them please make a PR to mention this plugin here.
+
+There are two modes of format validation: `fast` and `full`. This mode affects formats `date`, `time`, `date-time`, `uri`, `uri-reference`, and `email`. See [Options](#options) for details.
You can add additional formats and replace any of the formats above using [addFormat](#api-addformat) method.
The option `unknownFormats` allows changing the default behaviour when an unknown format is encountered. In this case Ajv can either fail schema compilation (default) or ignore it (default in versions before 5.0.0). You also can whitelist specific format(s) to be ignored. See [Options](#options) for details.
-You can find patterns used for format validation and the sources that were used in [formats.js](https://github.com/epoberezkin/ajv/blob/master/lib/compile/formats.js).
+You can find regular expressions used for format validation and the sources that were used in [formats.js](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js).
## Combining schemas with $ref
@@ -274,8 +371,8 @@ or use `addSchema` method:
```javascript
var ajv = new Ajv;
-ajv.addSchema(defsSchema);
-var validate = ajv.compile(schema);
+var validate = ajv.addSchema(defsSchema)
+ .compile(schema);
```
See [Options](#options) and [addSchema](#api) method.
@@ -292,7 +389,7 @@ __Please note__:
## $data reference
-With `$data` option you can use values from the validated data as the values for the schema keywords. See [proposal](https://github.com/json-schema/json-schema/wiki/$data-(v5-proposal)) for more information about how it works.
+With `$data` option you can use values from the validated data as the values for the schema keywords. See [proposal](https://github.com/json-schema-org/json-schema-spec/issues/51) for more information about how it works.
`$data` reference is supported in the keywords: const, enum, format, maximum/minimum, exclusiveMaximum / exclusiveMinimum, maxLength / minLength, maxItems / minItems, maxProperties / minProperties, formatMaximum / formatMinimum, formatExclusiveMaximum / formatExclusiveMinimum, multipleOf, pattern, required, uniqueItems.
@@ -344,7 +441,7 @@ var validData = {
## $merge and $patch keywords
-With the package [ajv-merge-patch](https://github.com/epoberezkin/ajv-merge-patch) you can use the keywords `$merge` and `$patch` that allow extending JSON-schemas with patches using formats [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) and [JSON Patch (RFC 6902)](https://tools.ietf.org/html/rfc6902).
+With the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) you can use the keywords `$merge` and `$patch` that allow extending JSON Schemas with patches using formats [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) and [JSON Patch (RFC 6902)](https://tools.ietf.org/html/rfc6902).
To add keywords `$merge` and `$patch` to Ajv instance use this code:
@@ -403,7 +500,7 @@ The schemas above are equivalent to this schema:
The properties `source` and `with` in the keywords `$merge` and `$patch` can use absolute or relative `$ref` to point to other schemas previously added to the Ajv instance or to the fragments of the current schema.
-See the package [ajv-merge-patch](https://github.com/epoberezkin/ajv-merge-patch) for more information.
+See the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) for more information.
## Defining custom keywords
@@ -418,7 +515,7 @@ The advantages of using custom keywords are:
If a keyword is used only for side-effects and its validation result is pre-defined, use option `valid: true/false` in keyword definition to simplify both generated code (no error handling in case of `valid: true`) and your keyword functions (no need to return any validation result).
-The concerns you have to be aware of when extending JSON-schema standard with custom keywords are the portability and understanding of your schemas. You will have to support these custom keywords on other platforms and to properly document these keywords so that everybody can understand them in your schemas.
+The concerns you have to be aware of when extending JSON Schema standard with custom keywords are the portability and understanding of your schemas. You will have to support these custom keywords on other platforms and to properly document these keywords so that everybody can understand them in your schemas.
You can define custom keywords with [addKeyword](#api-addkeyword) method. Keywords are defined on the `ajv` instance level - new instances will not have previously defined keywords.
@@ -431,14 +528,17 @@ Ajv allows defining keywords with:
Example. `range` and `exclusiveRange` keywords using compiled schema:
```javascript
-ajv.addKeyword('range', { type: 'number', compile: function (sch, parentSchema) {
- var min = sch[0];
- var max = sch[1];
+ajv.addKeyword('range', {
+ type: 'number',
+ compile: function (sch, parentSchema) {
+ var min = sch[0];
+ var max = sch[1];
- return parentSchema.exclusiveRange === true
- ? function (data) { return data > min && data < max; }
- : function (data) { return data >= min && data <= max; }
-} });
+ return parentSchema.exclusiveRange === true
+ ? function (data) { return data > min && data < max; }
+ : function (data) { return data >= min && data <= max; }
+ }
+});
var schema = { "range": [2, 4], "exclusiveRange": true };
var validate = ajv.compile(schema);
@@ -448,9 +548,9 @@ console.log(validate(2)); // false
console.log(validate(4)); // false
```
-Several custom keywords (typeof, instanceof, range and propertyNames) are defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package - they can be used for your schemas and as a starting point for your own custom keywords.
+Several custom keywords (typeof, instanceof, range and propertyNames) are defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package - they can be used for your schemas and as a starting point for your own custom keywords.
-See [Defining custom keywords](https://github.com/epoberezkin/ajv/blob/master/CUSTOM.md) for more details.
+See [Defining custom keywords](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md) for more details.
## Asynchronous schema compilation
@@ -489,17 +589,11 @@ If your schema uses asynchronous formats/keywords or refers to some schema that
__Please note__: all asynchronous subschemas that are referenced from the current or other schemas should have `"$async": true` keyword as well, otherwise the schema compilation will fail.
-Validation function for an asynchronous custom format/keyword should return a promise that resolves with `true` or `false` (or rejects with `new Ajv.ValidationError(errors)` if you want to return custom errors from the keyword function). Ajv compiles asynchronous schemas to either [es7 async functions](http://tc39.github.io/ecmascript-asyncawait/) that can optionally be transpiled with [nodent](https://github.com/MatAtBread/nodent) or with [regenerator](https://github.com/facebook/regenerator) or to [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) that can be optionally transpiled with regenerator as well. You can also supply any other transpiler as a function. See [Options](#options).
-
-The compiled validation function has `$async: true` property (if the schema is asynchronous), so you can differentiate these functions if you are using both synchronous and asynchronous schemas.
-
-If you are using generators, the compiled validation function can be either wrapped with [co](https://github.com/tj/co) (default) or returned as generator function, that can be used directly, e.g. in [koa](http://koajs.com/) 1.0. `co` is a small library, it is included in Ajv (both as npm dependency and in the browser bundle).
-
-Async functions are currently supported in Chrome 55, Firefox 52, Node.js 7 (with --harmony-async-await) and MS Edge 13 (with flag).
+Validation function for an asynchronous custom format/keyword should return a promise that resolves with `true` or `false` (or rejects with `new Ajv.ValidationError(errors)` if you want to return custom errors from the keyword function).
-Generator functions are currently supported in Chrome, Firefox and Node.js.
+Ajv compiles asynchronous schemas to [es7 async functions](http://tc39.github.io/ecmascript-asyncawait/) that can optionally be transpiled with [nodent](https://github.com/MatAtBread/nodent). Async functions are supported in Node.js 7+ and all modern browsers. You can also supply any other transpiler as a function via `processCode` option. See [Options](#options).
-If you are using Ajv in other browsers or in older versions of Node.js you should use one of available transpiling options. All provided async modes use global Promise class. If your platform does not have Promise you should use a polyfill that defines it.
+The compiled validation function has `$async: true` property (if the schema is asynchronous), so you can differentiate these functions if you are using both synchronous and asynchronous schemas.
Validation result will be a promise that resolves with validated data or rejects with an exception `Ajv.ValidationError` that contains the array of validation errors in `errors` property.
@@ -507,21 +601,8 @@ Validation result will be a promise that resolves with validated data or rejects
Example:
```javascript
-/**
- * Default mode is non-transpiled generator function wrapped with `co`.
- * Using package ajv-async (https://github.com/epoberezkin/ajv-async)
- * you can auto-detect the best async mode.
- * In this case, without "async" and "transpile" options
- * (or with option {async: true})
- * Ajv will choose the first supported/installed option in this order:
- * 1. native async function
- * 2. native generator function wrapped with co
- * 3. es7 async functions transpiled with nodent
- * 4. es7 async functions transpiled with regenerator
- */
-
-var setupAsync = require('ajv-async');
-var ajv = setupAsync(new Ajv);
+var ajv = new Ajv;
+// require('ajv-async')(ajv);
ajv.addKeyword('idExists', {
async: true,
@@ -568,66 +649,108 @@ validate({ userId: 1, postId: 19 })
### Using transpilers with asynchronous validation functions.
-To use a transpiler you should separately install it (or load its bundle in the browser).
-
-Ajv npm package includes minified browser bundles of regenerator and nodent in dist folder.
+[ajv-async](https://github.com/ajv-validator/ajv-async) uses [nodent](https://github.com/MatAtBread/nodent) to transpile async functions. To use another transpiler you should separately install it (or load its bundle in the browser).
#### Using nodent
```javascript
-var setupAsync = require('ajv-async');
-var ajv = new Ajv({ /* async: 'es7', */ transpile: 'nodent' });
-setupAsync(ajv);
+var ajv = new Ajv;
+require('ajv-async')(ajv);
+// in the browser if you want to load ajv-async bundle separately you can:
+// window.ajvAsync(ajv);
var validate = ajv.compile(schema); // transpiled es7 async function
validate(data).then(successFunc).catch(errorFunc);
```
-`npm install nodent` or use `nodent.min.js` from dist folder of npm package.
-
-#### Using regenerator
+#### Using other transpilers
```javascript
-var setupAsync = require('ajv-async');
-var ajv = new Ajv({ /* async: 'es7', */ transpile: 'regenerator' });
-setupAsync(ajv);
+var ajv = new Ajv({ processCode: transpileFunc });
var validate = ajv.compile(schema); // transpiled es7 async function
validate(data).then(successFunc).catch(errorFunc);
```
-`npm install regenerator` or use `regenerator.min.js` from dist folder of npm package.
+See [Options](#options).
-#### Using other transpilers
+## Security considerations
+
+JSON Schema, if properly used, can replace data sanitisation. It doesn't replace other API security considerations. It also introduces additional security aspects to consider.
+
+
+##### Security contact
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.
+
+
+##### Untrusted schemas
+
+Ajv treats JSON schemas as trusted as your application code. This security model is based on the most common use case, when the schemas are static and bundled together with the application.
+
+If your schemas are received from untrusted sources (or generated from untrusted data) there are several scenarios you need to prevent:
+- compiling schemas can cause stack overflow (if they are too deep)
+- compiling schemas can be slow (e.g. [#557](https://github.com/ajv-validator/ajv/issues/557))
+- validating certain data can be slow
+
+It is difficult to predict all the scenarios, but at the very least it may help to limit the size of untrusted schemas (e.g. limit JSON string length) and also the maximum schema object depth (that can be high for relatively small JSON strings). You also may want to mitigate slow regular expressions in `pattern` and `patternProperties` keywords.
+
+Regardless the measures you take, using untrusted schemas increases security risks.
+
+
+##### Circular references in JavaScript objects
+
+Ajv does not support schemas and validated data that have circular references in objects. See [issue #802](https://github.com/ajv-validator/ajv/issues/802).
+
+An attempt to compile such schemas or validate such data would cause stack overflow (or will not complete in case of asynchronous validation). Depending on the parser you use, untrusted data can lead to circular references.
+
+
+##### Security risks of trusted schemas
+
+Some keywords in JSON Schemas can lead to very slow validation for certain data. These keywords include (but may be not limited to):
+
+- `pattern` and `format` for large strings - in some cases using `maxLength` can help mitigate it, but certain regular expressions can lead to exponential validation time even with relatively short strings (see [ReDoS attack](#redos-attack)).
+- `patternProperties` for large property names - use `propertyNames` to mitigate, but some regular expressions can have exponential evaluation time as well.
+- `uniqueItems` for large non-scalar arrays - use `maxItems` to mitigate
+
+__Please note__: The suggestions above to prevent slow validation would only work if you do NOT use `allErrors: true` in production code (using it would continue validation after validation errors).
+
+You can validate your JSON schemas against [this meta-schema](https://github.com/ajv-validator/ajv/blob/master/lib/refs/json-schema-secure.json) to check that these recommendations are followed:
```javascript
-var ajv = new Ajv({ async: 'es7', processCode: transpileFunc });
-var validate = ajv.compile(schema); // transpiled es7 async function
-validate(data).then(successFunc).catch(errorFunc);
+const isSchemaSecure = ajv.compile(require('ajv/lib/refs/json-schema-secure.json'));
+
+const schema1 = {format: 'email'};
+isSchemaSecure(schema1); // false
+
+const schema2 = {format: 'email', maxLength: MAX_LENGTH};
+isSchemaSecure(schema2); // true
```
-See [Options](#options).
+__Please note__: following all these recommendation is not a guarantee that validation of untrusted data is safe - it can still lead to some undesirable results.
-#### Comparison of async modes
+##### Content Security Policies (CSP)
+See [Ajv and Content Security Policies (CSP)](#ajv-and-content-security-policies-csp)
-|mode|transpile speed*|run-time speed*|bundle size|
-|---|:-:|:-:|:-:|
-|es7 async (native)|-|0.75|-|
-|generators (native)|-|1.0|-|
-|es7.nodent|1.35|1.1|215Kb|
-|es7.regenerator|1.0|2.7|1109Kb|
-|regenerator|1.0|3.2|1109Kb|
-\* Relative performance in Node.js 7.x — smaller is better.
+## ReDoS attack
-[nodent](https://github.com/MatAtBread/nodent) has several advantages:
+Certain regular expressions can lead to the exponential evaluation time even with relatively short strings.
-- much smaller browser bundle than regenerator
-- almost the same performance of generated code as native generators in Node.js and the latest Chrome
-- much better performance than native generators in other browsers
-- works in IE 9 (regenerator does not)
+Please assess the regular expressions you use in the schemas on their vulnerability to this attack - see [safe-regex](https://github.com/substack/safe-regex), for example.
+
+__Please note__: some formats that Ajv implements use [regular expressions](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js) that can be vulnerable to ReDoS attack, so if you use Ajv to validate data from untrusted sources __it is strongly recommended__ to consider the following:
+
+- making assessment of "format" implementations in Ajv.
+- using `format: 'fast'` option that simplifies some of the regular expressions (although it does not guarantee that they are safe).
+- replacing format implementations provided by Ajv with your own implementations of "format" keyword that either uses different regular expressions or another approach to format validation. Please see [addFormat](#api-addformat) method.
+- disabling format validation by ignoring "format" keyword with option `format: false`
+
+Whatever mitigation you choose, please assume all formats provided by Ajv as potentially unsafe and make your own assessment of their suitability for your validation scenarios.
## Filtering data
@@ -700,7 +823,7 @@ The intention of the schema above is to allow objects with either the string pro
With the option `removeAdditional: true` the validation will pass for the object `{ "foo": "abc"}` but will fail for the object `{"bar": 1}`. It happens because while the first subschema in `oneOf` is validated, the property `bar` is removed because it is an additional property according to the standard (because it is not included in `properties` keyword in the same schema).
-While this behaviour is unexpected (issues [#129](https://github.com/epoberezkin/ajv/issues/129), [#134](https://github.com/epoberezkin/ajv/issues/134)), it is correct. To have the expected behaviour (both objects are allowed and additional properties are removed) the schema has to be refactored in this way:
+While this behaviour is unexpected (issues [#129](https://github.com/ajv-validator/ajv/issues/129), [#134](https://github.com/ajv-validator/ajv/issues/134)), it is correct. To have the expected behaviour (both objects are allowed and additional properties are removed) the schema has to be refactored in this way:
```json
{
@@ -724,13 +847,11 @@ The schema above is also more efficient - it will compile into a faster function
With [option `useDefaults`](#options) Ajv will assign values from `default` keyword in the schemas of `properties` and `items` (when it is the array of schemas) to the missing properties and items.
-This option modifies original data.
+With the option value `"empty"` properties and items equal to `null` or `""` (empty string) will be considered missing and assigned defaults.
-__Please note__: by default the default value is inserted in the generated validation code as a literal (starting from v4.0), so the value inserted in the data will be the deep clone of the default in the schema.
-
-If you need to insert the default value in the data by reference pass the option `useDefaults: "shared"`.
+This option modifies original data.
-Inserting defaults by reference can be faster (in case you have an object in `default`) and it allows to have dynamic values in defaults, e.g. timestamp, without recompiling the schema. The side effect is that modifying the default value in any validated data instance will change the default in the schema and in other validated data instances. See example 3 below.
+__Please note__: the default value is inserted in the generated validation code as a literal, so the value inserted in the data will be the deep clone of the default in the schema.
Example 1 (`default` in `properties`):
@@ -773,39 +894,15 @@ console.log(validate(data)); // true
console.log(data); // [ 1, "foo" ]
```
-Example 3 (inserting "defaults" by reference):
-
-```javascript
-var ajv = new Ajv({ useDefaults: 'shared' });
-
-var schema = {
- properties: {
- foo: {
- default: { bar: 1 }
- }
- }
-}
-
-var validate = ajv.compile(schema);
-
-var data = {};
-console.log(validate(data)); // true
-console.log(data); // { foo: { bar: 1 } }
-
-data.foo.bar = 2;
-
-var data2 = {};
-console.log(validate(data2)); // true
-console.log(data2); // { foo: { bar: 2 } }
-```
-
`default` keywords in other cases are ignored:
- not in `properties` or `items` subschemas
-- in schemas inside `anyOf`, `oneOf` and `not` (see [#42](https://github.com/epoberezkin/ajv/issues/42))
+- in schemas inside `anyOf`, `oneOf` and `not` (see [#42](https://github.com/ajv-validator/ajv/issues/42))
- in `if` subschema of `switch` keyword
- in schemas generated by custom macro keywords
+The [`strictDefaults` option](#options) customizes Ajv's behavior for the defaults that Ajv ignores (`true` raises an error, and `"log"` outputs a warning).
+
## Coercing data types
@@ -858,7 +955,7 @@ console.log(data); // { "foo": [1], "bar": false }
The coercion rules, as you can see from the example, are different from JavaScript both to validate user input as expected and to have the coercion reversible (to correctly validate cases where different types are defined in subschemas of "anyOf" and other compound keywords).
-See [Coercion rules](https://github.com/epoberezkin/ajv/blob/master/COERCION.md) for details.
+See [Coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md) for details.
## API
@@ -872,9 +969,9 @@ Create Ajv instance.
Generate validating function and cache the compiled schema for future use.
-Validating function returns boolean and has properties `errors` with the errors from the last validation (`null` if there were no errors) and `schema` with the reference to the original schema.
+Validating function returns a boolean value. This function has properties `errors` and `schema`. Errors encountered during the last validation are assigned to `errors` property (it is assigned `null` if there was no errors). `schema` property contains the reference to the original schema.
-Unless the option `validateSchema` is false, the schema will be validated against meta-schema and if schema is invalid the error will be thrown. See [options](#options).
+The schema passed to this method will be validated against meta-schema unless `validateSchema` option is false. If schema is invalid, an error will be thrown. See [options](#options).
##### .compileAsync(Object schema [, Boolean meta] [, Function callback]) -> Promise
@@ -905,7 +1002,7 @@ __Please note__: every time this method is called the errors are overwritten so
If the schema is asynchronous (has `$async` keyword on the top level) this method returns a Promise. See [Asynchronous validation](#asynchronous-validation).
-##### .addSchema(Array<Object>|Object schema [, String key])
+##### .addSchema(Array<Object>|Object schema [, String key]) -> Ajv
Add schema(s) to validator instance. This method does not compile schemas (but it still validates them). Because of that dependencies can be added in any order and circular dependencies are supported. It also prevents unnecessary compilation of schemas that are containers for other schemas but not used as a whole.
@@ -920,12 +1017,18 @@ Although `addSchema` does not compile schemas, explicit compilation is not requi
By default the schema is validated against meta-schema before it is added, and if the schema does not pass validation the exception is thrown. This behaviour is controlled by `validateSchema` option.
+__Please note__: Ajv uses the [method chaining syntax](https://en.wikipedia.org/wiki/Method_chaining) for all methods with the prefix `add*` and `remove*`.
+This allows you to do nice things like the following.
+
+```javascript
+var validate = new Ajv().addSchema(schema).addFormat(name, regex).getSchema(uri);
+```
-##### .addMetaSchema(Array<Object>|Object schema [, String key])
+##### .addMetaSchema(Array<Object>|Object schema [, String key]) -> Ajv
Adds meta schema(s) that can be used to validate other schemas. That function should be used instead of `addSchema` because there may be instance options that would compile a meta schema incorrectly (at the moment it is `removeAdditional` option).
-There is no need to explicitly add draft 6 meta schema (http://json-schema.org/draft-06/schema and http://json-schema.org/schema) - it is added by default, unless option `meta` is set to `false`. You only need to use it if you have a changed meta-schema that you want to use to validate your schemas. See `validateSchema`.
+There is no need to explicitly add draft-07 meta schema (http://json-schema.org/draft-07/schema) - it is added by default, unless option `meta` is set to `false`. You only need to use it if you have a changed meta-schema that you want to use to validate your schemas. See `validateSchema`.
##### .validateSchema(Object schema) -> Boolean
@@ -946,7 +1049,7 @@ Errors will be available at `ajv.errors`.
Retrieve compiled schema previously added with `addSchema` by the key passed to `addSchema` or by its full reference (id). The returned validating function has `schema` property with the reference to the original schema.
-##### .removeSchema([Object schema|String key|String ref|RegExp pattern])
+##### .removeSchema([Object schema|String key|String ref|RegExp pattern]) -> Ajv
Remove added/cached schema. Even if schema is referenced by other schemas it can be safely removed as dependent schemas have local references.
@@ -959,7 +1062,7 @@ Schema can be removed using:
If no parameter is passed all schemas but meta-schemas will be removed and the cache will be cleared.
-##### .addFormat(String name, String|RegExp|Function|Object format)
+##### .addFormat(String name, String|RegExp|Function|Object format) -> Ajv
Add custom format to validate strings or numbers. It can also be used to replace pre-defined formats for Ajv instance.
@@ -970,25 +1073,25 @@ Function should return validation result as `true` or `false`.
If object is passed it should have properties `validate`, `compare` and `async`:
- _validate_: a string, RegExp or a function as described above.
-- _compare_: an optional comparison function that accepts two strings and compares them according to the format meaning. This function is used with keywords `formatMaximum`/`formatMinimum` (defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package). It should return `1` if the first value is bigger than the second value, `-1` if it is smaller and `0` if it is equal.
+- _compare_: an optional comparison function that accepts two strings and compares them according to the format meaning. This function is used with keywords `formatMaximum`/`formatMinimum` (defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package). It should return `1` if the first value is bigger than the second value, `-1` if it is smaller and `0` if it is equal.
- _async_: an optional `true` value if `validate` is an asynchronous function; in this case it should return a promise that resolves with a value `true` or `false`.
-- _type_: an optional type of data that the format applies to. It can be `"string"` (default) or `"number"` (see https://github.com/epoberezkin/ajv/issues/291#issuecomment-259923858). If the type of data is different, the validation will pass.
+- _type_: an optional type of data that the format applies to. It can be `"string"` (default) or `"number"` (see https://github.com/ajv-validator/ajv/issues/291#issuecomment-259923858). If the type of data is different, the validation will pass.
Custom formats can be also added via `formats` option.
-##### .addKeyword(String keyword, Object definition)
+##### .addKeyword(String keyword, Object definition) -> Ajv
Add custom validation keyword to Ajv instance.
-Keyword should be different from all standard JSON schema keywords and different from previously defined keywords. There is no way to redefine keywords or to remove keyword definition from the instance.
+Keyword should be different from all standard JSON Schema keywords and different from previously defined keywords. There is no way to redefine keywords or to remove keyword definition from the instance.
Keyword must start with a letter, `_` or `$`, and may continue with letters, numbers, `_`, `$`, or `-`.
It is recommended to use an application-specific prefix for keywords to avoid current and future name collisions.
Example Keywords:
- `"xyz-example"`: valid, and uses prefix for the xyz project to avoid name collisions.
-- `"example"`: valid, but not recommended as it could collide with future versions of JSON schema etc.
+- `"example"`: valid, but not recommended as it could collide with future versions of JSON Schema etc.
- `"3-example"`: invalid as numbers are not allowed to be the first character in a keyword
Keyword definition is an object with the following properties:
@@ -1000,11 +1103,13 @@ Keyword definition is an object with the following properties:
- _inline_: compiling function that returns code (as string)
- _schema_: an optional `false` value used with "validate" keyword to not pass schema
- _metaSchema_: an optional meta-schema for keyword schema
+- _dependencies_: an optional list of properties that must be present in the parent schema - it will be checked during schema compilation
- _modifying_: `true` MUST be passed if keyword modifies data
+- _statements_: `true` can be passed in case inline keyword generates statements (as opposed to expression)
- _valid_: pass `true`/`false` to pre-define validation result, the result returned from validation function will be ignored. This option cannot be used with macro keywords.
- _$data_: an optional `true` value to support [$data reference](#data-reference) as the value of custom keyword. The reference will be resolved at validation time. If the keyword has meta-schema it would be extended to allow $data and it will be used to validate the resolved value. Supporting $data reference requires that keyword has validating function (as the only option or in addition to compile, macro or inline function).
- _async_: an optional `true` value if the validation function is asynchronous (whether it is compiled or passed in _validate_ property); in this case it should return a promise that resolves with a value `true` or `false`. This option is ignored in case of "macro" and "inline" keywords.
-- _errors_: an optional boolean indicating whether keyword returns errors. If this property is not set Ajv will determine if the errors were set in case of failed validation.
+- _errors_: an optional boolean or string `"full"` indicating whether keyword returns errors. If this property is not set Ajv will determine if the errors were set in case of failed validation.
_compile_, _macro_ and _inline_ are mutually exclusive, only one should be used at a time. _validate_ can be used separately or in addition to them to support $data reference.
@@ -1018,7 +1123,7 @@ See [Defining custom keywords](#defining-custom-keywords) for more details.
Returns custom keyword definition, `true` for pre-defined keywords and `false` if the keyword is unknown.
-##### .removeKeyword(String keyword)
+##### .removeKeyword(String keyword) -> Ajv
Removes custom or pre-defined keyword so you can redefine them.
@@ -1044,15 +1149,18 @@ Defaults:
$data: false,
allErrors: false,
verbose: false,
+ $comment: false, // NEW in Ajv version 6.0
jsonPointers: false,
uniqueItems: true,
unicode: true,
+ nullable: false,
format: 'fast',
formats: {},
unknownFormats: true,
schemas: {},
+ logger: undefined,
// referenced schema options:
- schemaId: undefined // recommended '$id'
+ schemaId: '$id',
missingRefs: true,
extendRefs: 'ignore', // recommended 'fail'
loadSchema: undefined, // function(uri: string): Promise {}
@@ -1060,8 +1168,11 @@ Defaults:
removeAdditional: false,
useDefaults: false,
coerceTypes: false,
+ // strict mode options
+ strictDefaults: false,
+ strictKeywords: false,
+ strictNumbers: false,
// asynchronous validation options:
- async: 'co*',
transpile: undefined, // requires ajv-async package
// advanced options:
meta: true,
@@ -1072,10 +1183,10 @@ Defaults:
loopRequired: Infinity,
ownProperties: false,
multipleOfPrecision: false,
- errorDataPath: 'object',
+ errorDataPath: 'object', // deprecated
messages: true,
sourceCode: false,
- processCode: undefined, // function (str: string): string {}
+ processCode: undefined, // function (str: string, schema: object): string {}
cache: new Cache,
serialize: undefined
}
@@ -1086,24 +1197,36 @@ Defaults:
- _$data_: support [$data references](#data-reference). Draft 6 meta-schema that is added by default will be extended to allow them. If you want to use another meta-schema you need to use $dataMetaSchema method to add support for $data reference. See [API](#api).
- _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).
+- _$comment_ (NEW in Ajv version 6.0): log or pass the value of `$comment` keyword to a function. Option values:
+ - `false` (default): ignore $comment keyword.
+ - `true`: log the keyword value to console.
+ - function: pass the keyword value, its schema path and root schema to the specified function
- _jsonPointers_: set `dataPath` property of errors using [JSON Pointers](https://tools.ietf.org/html/rfc6901) instead of JavaScript property access notation.
- _uniqueItems_: validate `uniqueItems` keyword (true by default).
- _unicode_: calculate correct length of strings with unicode pairs (true by default). Pass `false` to use `.length` of strings that is faster, but gives "incorrect" lengths of strings with unicode pairs - each unicode pair is counted as two characters.
-- _format_: formats validation mode ('fast' by default). Pass 'full' for more correct and slow validation or `false` not to validate formats at all. E.g., 25:00:00 and 2015/14/33 will be invalid time and date in 'full' mode but it will be valid in 'fast' mode.
+- _nullable_: support keyword "nullable" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).
+- _format_: formats validation mode. Option values:
+ - `"fast"` (default) - simplified and fast validation (see [Formats](#formats) for details of which formats are available and affected by this option).
+ - `"full"` - more restrictive and slow validation. E.g., 25:00:00 and 2015/14/33 will be invalid time and date in 'full' mode but it will be valid in 'fast' mode.
+ - `false` - ignore all format keywords.
- _formats_: an object with custom formats. Keys and values will be passed to `addFormat` method.
+- _keywords_: an object with custom keywords. Keys and values will be passed to `addKeyword` method.
- _unknownFormats_: handling of unknown formats. Option values:
- `true` (default) - if an unknown format is encountered the exception is thrown during schema compilation. If `format` keyword value is [$data reference](#data-reference) and it is unknown the validation will fail.
- `[String]` - an array of unknown format names that will be ignored. This option can be used to allow usage of third party schemas with format(s) for which you don't have definitions, but still fail if another unknown format is used. If `format` keyword value is [$data reference](#data-reference) and it is not in this array the validation will fail.
- - `"ignore"` - to log warning during schema compilation and always pass validation (the default behaviour in versions before 5.0.0). This option is not recommended, as it allows to mistype format name and it won't be validated without any error message. This behaviour is required by JSON-schema specification.
+ - `"ignore"` - to log warning during schema compilation and always pass validation (the default behaviour in versions before 5.0.0). This option is not recommended, as it allows to mistype format name and it won't be validated without any error message. This behaviour is required by JSON Schema specification.
- _schemas_: an array or object of schemas that will be added to the instance. In case you pass the array the schemas must have IDs in them. When the object is passed the method `addSchema(value, key)` will be called for each schema in this object.
+- _logger_: sets the logging method. Default is the global `console` object that should have methods `log`, `warn` and `error`. See [Error logging](#error-logging). Option values:
+ - custom logger - it should have methods `log`, `warn` and `error`. If any of these methods is missing an exception will be thrown.
+ - `false` - logging is disabled.
##### Referenced schema options
- _schemaId_: this option defines which keywords are used as schema URI. Option value:
- - `"$id"` (recommended) - only use `$id` keyword as schema URI (as specified in JSON Schema draft-06), ignore `id` keyword (if it is present a warning will be logged).
+ - `"$id"` (default) - only use `$id` keyword as schema URI (as specified in JSON Schema draft-06/07), ignore `id` keyword (if it is present a warning will be logged).
- `"id"` - only use `id` keyword as schema URI (as specified in JSON Schema draft-04), ignore `$id` keyword (if it is present a warning will be logged).
- - `undefined` (default) - use both `$id` and `id` keywords as schema URI. If both are present (in the same schema object) and different the exception will be thrown during schema compilation.
+ - `"auto"` - use both `$id` and `id` keywords as schema URI. If both are present (in the same schema object) and different the exception will be thrown during schema compilation.
- _missingRefs_: handling of missing referenced schemas. Option values:
- `true` (default) - if the reference cannot be resolved during compilation the exception is thrown. The thrown error has properties `missingRef` (with hash fragment) and `missingSchema` (without it). Both properties are resolved relative to the current base id (usually schema id, unless it was substituted).
- `"ignore"` - to log error during compilation and always pass validation.
@@ -1122,42 +1245,43 @@ Defaults:
- `"all"` - all additional properties are removed, regardless of `additionalProperties` keyword in schema (and no validation is made for them).
- `true` - only additional properties with `additionalProperties` keyword equal to `false` are removed.
- `"failing"` - additional properties that fail schema validation will be removed (where `additionalProperties` keyword is `false` or schema).
-- _useDefaults_: replace missing properties and items with the values from corresponding `default` keywords. Default behaviour is to ignore `default` keywords. This option is not used if schema is added with `addMetaSchema` method. See examples in [Assigning defaults](#assigning-defaults). Option values:
+- _useDefaults_: replace missing or undefined properties and items with the values from corresponding `default` keywords. Default behaviour is to ignore `default` keywords. This option is not used if schema is added with `addMetaSchema` method. See examples in [Assigning defaults](#assigning-defaults). Option values:
- `false` (default) - do not use defaults
- - `true` - insert defaults by value (safer and slower, object literal is used).
- - `"shared"` - insert defaults by reference (faster). If the default is an object, it will be shared by all instances of validated data. If you modify the inserted default in the validated data, it will be modified in the schema as well.
-- _coerceTypes_: change data type of data to match `type` keyword. See the example in [Coercing data types](#coercing-data-types) and [coercion rules](https://github.com/epoberezkin/ajv/blob/master/COERCION.md). Option values:
+ - `true` - insert defaults by value (object literal is used).
+ - `"empty"` - in addition to missing or undefined, use defaults for properties and items that are equal to `null` or `""` (an empty string).
+ - `"shared"` (deprecated) - insert defaults by reference. If the default is an object, it will be shared by all instances of validated data. If you modify the inserted default in the validated data, it will be modified in the schema as well.
+- _coerceTypes_: change data type of data to match `type` keyword. See the example in [Coercing data types](#coercing-data-types) and [coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md). Option values:
- `false` (default) - no type coercion.
- `true` - coerce scalar data types.
- `"array"` - in addition to coercions between scalar types, coerce scalar data to an array with one element and vice versa (as required by the schema).
+##### Strict mode options
+
+- _strictDefaults_: report ignored `default` keywords in schemas. Option values:
+ - `false` (default) - ignored defaults are not reported
+ - `true` - if an ignored default is present, throw an error
+ - `"log"` - if an ignored default is present, log warning
+- _strictKeywords_: report unknown keywords in schemas. Option values:
+ - `false` (default) - unknown keywords are not reported
+ - `true` - if an unknown keyword is present, throw an error
+ - `"log"` - if an unknown keyword is present, log warning
+- _strictNumbers_: validate numbers strictly, failing validation for NaN and Infinity. Option values:
+ - `false` (default) - NaN or Infinity will pass validation for numeric types
+ - `true` - NaN or Infinity will not pass validation for numeric types
+
##### Asynchronous validation options
-- _async_: determines how Ajv compiles asynchronous schemas (see [Asynchronous validation](#asynchronous-validation)) to functions. Option values:
- - `"*"` / `"co*"` (default) - compile to generator function ("co*" - wrapped with `co.wrap`). If generators are not supported and you don't provide `processCode` option (or `transpile` option if you use [ajv-async](https://github.com/epoberezkin/ajv-async) package), the exception will be thrown when async schema is compiled.
- - `"es7"` - compile to es7 async function. Unless your platform supports them you need to provide `processCode` or `transpile` option. According to [compatibility table](http://kangax.github.io/compat-table/es7/)) async functions are supported by:
- - Firefox 52,
- - Chrome 55,
- - Node.js 7 (with `--harmony-async-await`),
- - MS Edge 13 (with flag).
- - `undefined`/`true` - auto-detect async mode. It requires [ajv-async](https://github.com/epoberezkin/ajv-async) package. If `transpile` option is not passed, ajv-async will choose the first of supported/installed async/transpile modes in this order:
- - "es7" (native async functions),
- - "co*" (native generators with co.wrap),
- - "es7"/"nodent",
- - "co*"/"regenerator" during the creation of the Ajv instance.
-
- If none of the options is available the exception will be thrown.
-- _transpile_: Requires [ajv-async](https://github.com/epoberezkin/ajv-async) package. It determines whether Ajv transpiles compiled asynchronous validation function. Option values:
- - `"nodent"` - transpile with [nodent](https://github.com/MatAtBread/nodent). If nodent is not installed, the exception will be thrown. nodent can only transpile es7 async functions; it will enforce this mode.
- - `"regenerator"` - transpile with [regenerator](https://github.com/facebook/regenerator). If regenerator is not installed, the exception will be thrown.
- - a function - this function should accept the code of validation function as a string and return transpiled code. This option allows you to use any other transpiler you prefer. If you are passing a function, you can simply pass it to `processCode` option without using ajv-async.
+- _transpile_: Requires [ajv-async](https://github.com/ajv-validator/ajv-async) package. It determines whether Ajv transpiles compiled asynchronous validation function. Option values:
+ - `undefined` (default) - transpile with [nodent](https://github.com/MatAtBread/nodent) if async functions are not supported.
+ - `true` - always transpile with nodent.
+ - `false` - do not transpile; if async functions are not supported an exception will be thrown.
##### Advanced options
- _meta_: add [meta-schema](http://json-schema.org/documentation.html) so it can be used by other schemas (true by default). If an object is passed, it will be used as the default meta-schema for schemas that have no `$schema` keyword. This default meta-schema MUST have `$schema` keyword.
-- _validateSchema_: validate added/compiled schemas against meta-schema (true by default). `$schema` property in the schema can either be http://json-schema.org/schema or http://json-schema.org/draft-04/schema or absent (draft-4 meta-schema will be used) or can be a reference to the schema previously added with `addMetaSchema` method. Option values:
+- _validateSchema_: validate added/compiled schemas against meta-schema (true by default). `$schema` property in the schema can be http://json-schema.org/draft-07/schema or absent (draft-07 meta-schema will be used) or can be a reference to the schema previously added with `addMetaSchema` method. Option values:
- `true` (default) - if the validation fails, throw the exception.
- `"log"` - if the validation fails, log error.
- `false` - skip schema validation.
@@ -1169,15 +1293,15 @@ Defaults:
- _passContext_: pass validation context to custom keyword functions. If this option is `true` and you pass some context to the compiled validation function with `validate.call(context, data)`, the `context` will be available as `this` in your custom keywords. By default `this` is Ajv instance.
- _loopRequired_: by default `required` keyword is compiled into a single expression (or a sequence of statements in `allErrors` mode). In case of a very large number of properties in this keyword it may result in a very big validation function. Pass integer to set the number of properties above which `required` keyword will be validated in a loop - smaller validation function size but also worse performance.
- _ownProperties_: by default Ajv iterates over all enumerable object properties; when this option is `true` only own enumerable object properties (i.e. found directly on the object rather than on its prototype) are iterated. Contributed by @mbroadst.
-- _multipleOfPrecision_: by default `multipleOf` keyword is validated by comparing the result of division with parseInt() of that result. It works for dividers that are bigger than 1. For small dividers such as 0.01 the result of the division is usually not integer (even when it should be integer, see issue [#84](https://github.com/epoberezkin/ajv/issues/84)). If you need to use fractional dividers set this option to some positive integer N to have `multipleOf` validated using this formula: `Math.abs(Math.round(division) - division) < 1e-N` (it is slower but allows for float arithmetics deviations).
-- _errorDataPath_: set `dataPath` to point to 'object' (default) or to 'property' when validating keywords `required`, `additionalProperties` and `dependencies`.
-- _messages_: Include human-readable messages in errors. `true` by default. `false` can be passed when custom messages are used (e.g. with [ajv-i18n](https://github.com/epoberezkin/ajv-i18n)).
+- _multipleOfPrecision_: by default `multipleOf` keyword is validated by comparing the result of division with parseInt() of that result. It works for dividers that are bigger than 1. For small dividers such as 0.01 the result of the division is usually not integer (even when it should be integer, see issue [#84](https://github.com/ajv-validator/ajv/issues/84)). If you need to use fractional dividers set this option to some positive integer N to have `multipleOf` validated using this formula: `Math.abs(Math.round(division) - division) < 1e-N` (it is slower but allows for float arithmetics deviations).
+- _errorDataPath_ (deprecated): set `dataPath` to point to 'object' (default) or to 'property' when validating keywords `required`, `additionalProperties` and `dependencies`.
+- _messages_: Include human-readable messages in errors. `true` by default. `false` can be passed when custom messages are used (e.g. with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n)).
- _sourceCode_: add `sourceCode` property to validating function (for debugging; this code can be different from the result of toString call).
- _processCode_: an optional function to process generated code before it is passed to Function constructor. It can be used to either beautify (the validating function is generated without line-breaks) or to transpile code. Starting from version 5.0.0 this option replaced options:
- - `beautify` that formatted the generated function using [js-beautify](https://github.com/beautify-web/js-beautify). If you want to beautify the generated code pass `require('js-beautify').js_beautify`.
- - `transpile` that transpiled asynchronous validation function. You can still use `transpile` option with [ajv-async](https://github.com/epoberezkin/ajv-async) package. See [Asynchronous validation](#asynchronous-validation) for more information.
+ - `beautify` that formatted the generated function using [js-beautify](https://github.com/beautify-web/js-beautify). If you want to beautify the generated code pass a function calling `require('js-beautify').js_beautify` as `processCode: code => js_beautify(code)`.
+ - `transpile` that transpiled asynchronous validation function. You can still use `transpile` option with [ajv-async](https://github.com/ajv-validator/ajv-async) package. See [Asynchronous validation](#asynchronous-validation) for more information.
- _cache_: an optional instance of cache to store compiled schemas using stable-stringified schema as a key. For example, set-associative cache [sacjs](https://github.com/epoberezkin/sacjs) can be used. If not passed then a simple hash is used which is good enough for the common use case (a limited number of statically defined schemas). Cache should have methods `put(key, value)`, `get(key)`, `del(key)` and `clear()`.
-- _serialize_: an optional function to serialize schema to cache key. Pass `false` to use schema itself as a key (e.g., if WeakMap used as a cache). By default [json-stable-stringify](https://github.com/substack/json-stable-stringify) is used.
+- _serialize_: an optional function to serialize schema to cache key. Pass `false` to use schema itself as a key (e.g., if WeakMap used as a cache). By default [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used.
## Validation errors
@@ -1192,7 +1316,7 @@ Each error is an object with the following properties:
- _keyword_: validation keyword.
- _dataPath_: the path to the part of the data that was validated. By default `dataPath` uses JavaScript property access notation (e.g., `".prop[1].subProp"`). When the option `jsonPointers` is true (see [Options](#options)) `dataPath` will be set using JSON pointer standard (e.g., `"/prop/1/subProp"`).
- _schemaPath_: the path (JSON-pointer as a URI fragment) to the schema of the keyword that failed validation.
-- _params_: the object with the additional information about error that can be used to create custom error messages (e.g., using [ajv-i18n](https://github.com/epoberezkin/ajv-i18n) package). See below for parameters set by all keywords.
+- _params_: the object with the additional information about error that can be used to create custom error messages (e.g., using [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package). See below for parameters set by all keywords.
- _message_: the standard error message (can be excluded with option `messages` set to false).
- _schema_: the schema of the keyword (added with `verbose` option).
- _parentSchema_: the schema containing the keyword (added with `verbose` option)
@@ -1225,20 +1349,59 @@ Properties of `params` object in errors depend on the keyword that failed valida
- `patternRequired` (in ajv-keywords) - 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).
+- `const` - property `allowedValue` pointing to the value (the schema of the keyword).
- `enum` - property `allowedValues` pointing to the array of values (the schema of the keyword).
- `$ref` - property `ref` with the referenced schema URI.
+- `oneOf` - property `passingSchemas` (array of indices of passing schemas, null if no schema passes).
- custom keywords (in case keyword definition doesn't create errors) - property `keyword` (the keyword name).
-## Related packages
+### Error logging
+
+Using the `logger` option when initiallizing Ajv will allow you to define custom logging. Here you can build upon the exisiting logging. The use of other logging packages is supported as long as the package or its associated wrapper exposes the required methods. If any of the required methods are missing an exception will be thrown.
+- **Required Methods**: `log`, `warn`, `error`
-- [ajv-cli](https://github.com/epoberezkin/ajv-cli) - command line interface for Ajv
-- [ajv-i18n](https://github.com/epoberezkin/ajv-i18n) - internationalised error messages
-- [ajv-merge-patch](https://github.com/epoberezkin/ajv-merge-patch) - keywords $merge and $patch.
-- [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) - several custom keywords that can be used with Ajv (typeof, instanceof, range, propertyNames)
-- [ajv-errors](https://github.com/epoberezkin/ajv-errors) - custom error messages for Ajv
+```javascript
+var otherLogger = new OtherLogger();
+var ajv = new Ajv({
+ logger: {
+ log: console.log.bind(console),
+ warn: function warn() {
+ otherLogger.logWarn.apply(otherLogger, arguments);
+ },
+ error: function error() {
+ otherLogger.logError.apply(otherLogger, arguments);
+ console.error.apply(console, arguments);
+ }
+ }
+});
+```
+## Plugins
+
+Ajv can be extended with plugins that add custom keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:
+
+- it exports a function
+- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining
+- this function can accept an optional configuration as the second parameter
+
+If you have published a useful plugin please submit a PR to add it to the next section.
+
+
+## Related packages
+
+- [ajv-async](https://github.com/ajv-validator/ajv-async) - plugin to configure async validation mode
+- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats
+- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface
+- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for custom error messages
+- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages
+- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas
+- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with custom validation keywords (select, typeof, etc.)
+- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch
+- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions
+- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't already included in ajv (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).
+
## Some packages using Ajv
- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser
@@ -1246,7 +1409,7 @@ Properties of `params` object in errors depend on the keyword that failed valida
- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition
- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator
- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org
-- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON-schema http://jsonschemalint.com
+- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com
- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js
- [table](https://github.com/gajus/table) - formats data into a string table
- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser
@@ -1255,12 +1418,13 @@ Properties of `params` object in errors depend on the keyword that failed valida
- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation
- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages
- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema
-- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON-schema with expect in mocha tests
+- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests
- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema
- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file
- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app
- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter
- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages
+- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX
## Tests
@@ -1273,30 +1437,42 @@ npm test
## Contributing
-All validation functions are generated using doT templates in [dot](https://github.com/epoberezkin/ajv/tree/master/lib/dot) folder. Templates are precompiled so doT is not a run-time dependency.
+All validation functions are generated using doT templates in [dot](https://github.com/ajv-validator/ajv/tree/master/lib/dot) folder. Templates are precompiled so doT is not a run-time dependency.
-`npm run build` - compiles templates to [dotjs](https://github.com/epoberezkin/ajv/tree/master/lib/dotjs) folder.
+`npm run build` - compiles templates to [dotjs](https://github.com/ajv-validator/ajv/tree/master/lib/dotjs) folder.
`npm run watch` - automatically compiles templates when files in dot folder change
-Please see [Contributing guidelines](https://github.com/epoberezkin/ajv/blob/master/CONTRIBUTING.md)
+Please see [Contributing guidelines](https://github.com/ajv-validator/ajv/blob/master/CONTRIBUTING.md)
## Changes history
-See https://github.com/epoberezkin/ajv/releases
+See https://github.com/ajv-validator/ajv/releases
+
+__Please note__: [Changes in version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).
+
+[Version 5.0.0](https://github.com/ajv-validator/ajv/releases/tag/5.0.0).
+
+[Version 4.0.0](https://github.com/ajv-validator/ajv/releases/tag/4.0.0).
+
+[Version 3.0.0](https://github.com/ajv-validator/ajv/releases/tag/3.0.0).
+
+[Version 2.0.0](https://github.com/ajv-validator/ajv/releases/tag/2.0.0).
+
+
+## Code of conduct
-__Please note__: [Changes in version 5.0.0](https://github.com/epoberezkin/ajv/releases/tag/5.0.0).
+Please review and follow the [Code of conduct](https://github.com/ajv-validator/ajv/blob/master/CODE_OF_CONDUCT.md).
-[Changes in version 4.6.0](https://github.com/epoberezkin/ajv/releases/tag/4.6.0).
+Please report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.
-[Changes in version 4.0.0](https://github.com/epoberezkin/ajv/releases/tag/4.0.0).
-[Changes in version 3.0.0](https://github.com/epoberezkin/ajv/releases/tag/3.0.0).
+## Open-source software support
-[Changes in version 2.0.0](https://github.com/epoberezkin/ajv/releases/tag/2.0.0).
+Ajv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.
## License
-[MIT](https://github.com/epoberezkin/ajv/blob/master/LICENSE)
+[MIT](https://github.com/ajv-validator/ajv/blob/master/LICENSE)
diff --git a/bower.json b/bower.json
index 048c089b6..507989c62 100644
--- a/bower.json
+++ b/bower.json
@@ -11,7 +11,7 @@
"schema",
"validator"
],
- "homepage": "https://github.com/epoberezkin/ajv",
+ "homepage": "https://github.com/ajv-validator/ajv",
"moduleType": [
"amd",
"globals",
diff --git a/karma.conf.js b/karma.conf.js
index 1ffca9b0f..155d0874e 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -17,8 +17,7 @@ module.exports = function(config) {
files: [
'dist/ajv.min.js',
'node_modules/chai/chai.js',
- 'dist/regenerator.min.js',
- 'dist/nodent.min.js',
+ 'node_modules/ajv-async/dist/ajv-async.min.js',
'node_modules/bluebird/js/browser/bluebird.core.min.js',
'.browser/*.spec.js'
],
@@ -54,8 +53,13 @@ module.exports = function(config) {
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
- browsers: ['Chrome'],
-
+ browsers: ['HeadlessChrome'],
+ customLaunchers: {
+ HeadlessChrome:{
+ base: 'ChromeHeadless',
+ flags: ['--no-sandbox']
+ },
+ },
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
diff --git a/karma.sauce.js b/karma.sauce.js
index 1316ab0e5..fac172e36 100644
--- a/karma.sauce.js
+++ b/karma.sauce.js
@@ -22,29 +22,18 @@ module.exports = function(config) {
browserName: 'chrome',
version: '27'
},
- // 'SL_Chrome_37': {
- // base: 'SauceLabs',
- // browserName: 'chrome',
- // version: '37'
- // },
'SL_Chrome': {
base: 'SauceLabs',
browserName: 'chrome'
},
- 'SL_InternetExplorer_9': {
- base: 'SauceLabs',
- browserName: 'internet explorer',
- version: '9'
- },
'SL_InternetExplorer_10': {
base: 'SauceLabs',
browserName: 'internet explorer',
version: '10'
},
- 'SL_InternetExplorer_11': {
+ 'SL_InternetExplorer': {
base: 'SauceLabs',
- browserName: 'internet explorer',
- version: '11' // default
+ browserName: 'internet explorer'
},
'SL_MicrosoftEdge': {
base: 'SauceLabs',
@@ -55,45 +44,32 @@ module.exports = function(config) {
browserName: 'firefox',
version: '17'
},
- // 'SL_FireFox_24': {
- // base: 'SauceLabs',
- // browserName: 'firefox',
- // version: '24'
- // },
'SL_FireFox': {
base: 'SauceLabs',
browserName: 'firefox'
},
- 'SL_Safari_5': {
+ 'SL_Safari_7': {
base: 'SauceLabs',
browserName: 'safari',
- version: '5' // default
+ version: '7'
},
- // 'SL_Safari_7': {
- // base: 'SauceLabs',
- // browserName: 'safari',
- // version: '7'
- // },
- 'SL_Safari_9': {
+ 'SL_Safari': {
base: 'SauceLabs',
- browserName: 'safari',
- version: '9'
+ browserName: 'safari'
},
'SL_iPhone_8': {
base: 'SauceLabs',
browserName: 'iphone',
version: '8.4'
},
- 'SL_iPhone_9': {
+ 'SL_iPhone': {
base: 'SauceLabs',
- browserName: 'iphone',
- version: '9.2'
+ browserName: 'iphone'
+ },
+ 'SL_Android': {
+ base: 'SauceLabs',
+ browserName: 'android'
}
- // 'SL_Android_4': {
- // base: 'SauceLabs',
- // browserName: 'android',
- // version: '4'
- // }
};
@@ -112,7 +88,7 @@ module.exports = function(config) {
files: [
'dist/ajv.min.js',
'node_modules/chai/chai.js',
- 'dist/nodent.min.js',
+ 'node_modules/ajv-async/dist/ajv-async.min.js',
'node_modules/bluebird/js/browser/bluebird.core.min.js',
'.browser/*.spec.js'
],
diff --git a/lib/ajv.d.ts b/lib/ajv.d.ts
index 2a8ee1898..cc2881b33 100644
--- a/lib/ajv.d.ts
+++ b/lib/ajv.d.ts
@@ -1,125 +1,165 @@
-declare var ajv: {
+declare var ajv: {
(options?: ajv.Options): ajv.Ajv;
- new (options?: ajv.Options): ajv.Ajv;
- ValidationError: ValidationError;
- MissingRefError: MissingRefError;
- $dataMetaSchema: Object;
+ new(options?: ajv.Options): ajv.Ajv;
+ ValidationError: typeof AjvErrors.ValidationError;
+ MissingRefError: typeof AjvErrors.MissingRefError;
+ $dataMetaSchema: object;
+}
+
+declare namespace AjvErrors {
+ class ValidationError extends Error {
+ constructor(errors: Array);
+
+ message: string;
+ errors: Array;
+ ajv: true;
+ validation: true;
+ }
+
+ class MissingRefError extends Error {
+ constructor(baseId: string, ref: string, message?: string);
+ static message: (baseId: string, ref: string) => string;
+
+ message: string;
+ missingRef: string;
+ missingSchema: string;
+ }
}
declare namespace ajv {
+ type ValidationError = AjvErrors.ValidationError;
+
+ type MissingRefError = AjvErrors.MissingRefError;
+
interface Ajv {
/**
* Validate data using schema
- * Schema will be compiled and cached (using serialized JSON as key, [json-stable-stringify](https://github.com/substack/json-stable-stringify) is used to serialize by default).
- * @param {String|Object|Boolean} schemaKeyRef key, ref or schema object
+ * Schema will be compiled and cached (using serialized JSON as key, [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize by default).
+ * @param {string|object|Boolean} schemaKeyRef key, ref or schema object
* @param {Any} data to be validated
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
*/
- validate(schemaKeyRef: Object | string | boolean, data: any): boolean | Thenable;
+ validate(schemaKeyRef: object | string | boolean, data: any): boolean | PromiseLike;
/**
* Create validating function for passed schema.
- * @param {Object|Boolean} schema schema object
+ * @param {object|Boolean} schema schema object
* @return {Function} validating function
*/
- compile(schema: Object | boolean): ValidateFunction;
+ compile(schema: object | boolean): ValidateFunction;
/**
* Creates validating function for passed schema with asynchronous loading of missing schemas.
* `loadSchema` option should be a function that accepts schema uri and node-style callback.
* @this Ajv
- * @param {Object|Boolean} schema schema object
+ * @param {object|Boolean} schema schema object
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
* @param {Function} callback optional node-style callback, it is always called with 2 parameters: error (or null) and validating function.
- * @return {Thenable} validating function
+ * @return {PromiseLike} validating function
*/
- compileAsync(schema: Object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): Thenable;
+ compileAsync(schema: object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): PromiseLike;
/**
* Adds schema to the instance.
- * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
- * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
+ * @param {object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
+ * @param {string} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
+ * @return {Ajv} this for method chaining
*/
- addSchema(schema: Array