Skip to content

Commit

Permalink
Merge pull request #1252 from ajv-validator/v7-alpha-remove-draft4
Browse files Browse the repository at this point in the history
v7 alpha - remove draft4
  • Loading branch information
epoberezkin committed Jul 27, 2020
2 parents 166d2df + 44e5d55 commit 6cede7b
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 536 deletions.
12 changes: 4 additions & 8 deletions KEYWORDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,9 @@ 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-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.
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-04 and draft-06/07 syntaxes.
**Please note**: Boolean value for keywords `exclusiveMaximum` (`exclusiveMinimum`) is no longer supported.

**Examples**

Expand All @@ -90,15 +88,13 @@ Ajv supports both draft-04 and draft-06/07 syntaxes.

_invalid_: `6`, `7`

2) _schema_: `{ "minimum": 5 }`
2. _schema_: `{ "minimum": 5 }`

_valid_: `5`, `6`, any non-number (`"abc"`, `[]`, `{}`, `null`, `true`)

_invalid_: `4`, `4.5`

3. _schema_:
draft-04: `{ "minimum": 5, "exclusiveMinimum": true }`
draft-06/07: `{ "exclusiveMinimum": 5 }`
3. _schema_: `{ "exclusiveMinimum": 5 }`

_valid_: `6`, `7`, any non-number (`"abc"`, `[]`, `{}`, `null`, `true`)

Expand Down
18 changes: 3 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Ajv: Another JSON Schema Validator

The fastest JSON Schema validator for Node.js and browser. Supports draft-04/06/07.
The fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).

[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)
[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)
Expand Down Expand Up @@ -63,14 +63,7 @@ Thank you
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"))
```
**Please note**: use Ajv v6 if you need draft-04 support - v7 does NOT support it.

## Contents

Expand Down Expand Up @@ -128,7 +121,7 @@ Performance of different validators by [json-schema-benchmark](https://github.co

## Features

- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) and draft-04 standards:
- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):
- 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
Expand Down Expand Up @@ -1122,7 +1115,6 @@ Defaults:
schemas: {},
logger: undefined,
// referenced schema options:
schemaId: '$id',
missingRefs: true,
extendRefs: 'ignore', // recommended 'fail'
loadSchema: undefined, // function(uri: string): Promise {}
Expand Down Expand Up @@ -1183,10 +1175,6 @@ Defaults:

##### Referenced schema options

- _schemaId_: this option defines which keywords are used as schema URI. Option value:
- `"$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).
- `"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.
Expand Down
1 change: 0 additions & 1 deletion lib/ajv.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ declare namespace ajv {
keywords?: object
unknownFormats?: true | string[] | "ignore"
schemas?: Array<object> | object
schemaId?: "$id" | "id" | "auto"
missingRefs?: true | "ignore" | "fail"
extendRefs?: true | "ignore" | "fail"
loadSchema?: (
Expand Down
40 changes: 6 additions & 34 deletions lib/ajv.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ function Ajv(opts) {
this._loadingSchemas = {}
this._compilations = []
this.RULES = rules()
this._getId = chooseGetId(opts)
if (opts.schemaId !== undefined && opts.schemaId !== "$id")
throw new Error("option schemaId is not supported from v7")

opts.loopRequired = opts.loopRequired || Infinity
if (opts.errorDataPath == "property") opts._errorDataPathProperty = true
Expand Down Expand Up @@ -134,7 +135,7 @@ function addSchema(schema, key, _skipValidation, _meta) {
this.addSchema(schema[i], undefined, _skipValidation, _meta)
return this
}
var id = this._getId(schema)
var id = schema.$id
if (id !== undefined && typeof id != "string")
throw new Error("schema id must be string")
key = resolve.normalizeId(key || id)
Expand Down Expand Up @@ -187,7 +188,7 @@ function defaultMeta(self) {
var meta = self._opts.meta
self._opts.defaultMeta =
typeof meta == "object"
? self._getId(meta) || meta
? meta.$id || meta
: self.getSchema(META_SCHEMA_ID)
? META_SCHEMA_ID
: undefined
Expand Down Expand Up @@ -267,7 +268,7 @@ function removeSchema(schemaKeyRef) {
var serialize = this._opts.serialize
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef
this._cache.del(cacheKey)
var id = this._getId(schemaKeyRef)
var id = schemaKeyRef.$id
if (id) {
id = resolve.normalizeId(id)
delete this._schemas[id]
Expand Down Expand Up @@ -298,7 +299,7 @@ function _addSchema(schema, skipValidation, meta, shouldAddSchema) {

shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false

var id = resolve.normalizeId(this._getId(schema))
var id = resolve.normalizeId(schema.$id)
if (id && shouldAddSchema) checkUnique(this, id)

var willValidate = this._opts.validateSchema !== false && !skipValidation
Expand Down Expand Up @@ -372,35 +373,6 @@ function _compile(schemaObj, root) {
}
}

function chooseGetId(opts) {
switch (opts.schemaId) {
case "auto":
return _get$IdOrId
case "id":
return _getId
default:
return _get$Id
}
}

/* @this Ajv */
function _getId(schema) {
if (schema.$id) this.logger.warn("schema $id ignored", schema.$id)
return schema.id
}

/* @this Ajv */
function _get$Id(schema) {
if (schema.id) this.logger.warn("schema id ignored", schema.id)
return schema.$id
}

function _get$IdOrId(schema) {
if (schema.$id && schema.id && schema.$id != schema.id)
throw new Error("schema $id is different from id")
return schema.$id || schema.id
}

/**
* Convert array of error message objects to string
* @this Ajv
Expand Down
12 changes: 6 additions & 6 deletions lib/compile/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function resolveSchema(root, ref) {
/* jshint validthis: true */
var p = URI.parse(ref),
refPath = _getFullPath(p),
baseId = getFullPath(this._getId(root.schema))
baseId = getFullPath(root.schema.$id)
if (Object.keys(root.schema).length === 0 || refPath !== baseId) {
var id = normalizeId(refPath)
var refVal = this._refs[id]
Expand All @@ -91,7 +91,7 @@ function resolveSchema(root, ref) {
}
}
if (!root.schema) return
baseId = getFullPath(this._getId(root.schema))
baseId = getFullPath(root.schema.$id)
}
return getJsonPointer.call(this, p, baseId, root.schema, root)
}
Expand All @@ -104,7 +104,7 @@ function resolveRecursive(root, ref, parsedRef) {
var schema = res.schema
var baseId = res.baseId
root = res.root
var id = this._getId(schema)
var id = schema.$id
if (id) baseId = resolveUrl(baseId, id)
return getJsonPointer.call(this, parsedRef, baseId, schema, root)
}
Expand Down Expand Up @@ -132,7 +132,7 @@ function getJsonPointer(parsedRef, baseId, schema, root) {
if (schema === undefined) break
var id
if (!PREVENT_SCOPE_CHANGE[part]) {
id = this._getId(schema)
id = schema.$id
if (id) baseId = resolveUrl(baseId, id)
if (schema.$ref) {
var $ref = resolveUrl(baseId, schema.$ref)
Expand Down Expand Up @@ -236,7 +236,7 @@ function resolveUrl(baseId, id) {

/* @this Ajv */
function resolveIds(schema) {
var schemaId = normalizeId(this._getId(schema))
var schemaId = normalizeId(schema.$id)
var baseIds = {"": schemaId}
var fullPaths = {"": getFullPath(schemaId, false)}
var localRefs = {}
Expand All @@ -252,7 +252,7 @@ function resolveIds(schema) {
keyIndex
) {
if (jsonPtr === "") return
var id = self._getId(sch)
var id = sch.$id
var baseId = baseIds[parentJsonPtr]
var fullPath = fullPaths[parentJsonPtr] + "/" + parentKeyword
if (keyIndex !== undefined) {
Expand Down
6 changes: 4 additions & 2 deletions lib/compile/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ module.exports = function rules() {
{
type: "number",
rules: [
{maximum: ["exclusiveMaximum"]},
{minimum: ["exclusiveMinimum"]},
"maximum",
"minimum",
"exclusiveMaximum",
"exclusiveMinimum",
"multipleOf",
"format",
],
Expand Down
115 changes: 12 additions & 103 deletions lib/dot/_limit.jst
Original file line number Diff line number Diff line change
Expand Up @@ -3,111 +3,20 @@
{{# def.setupKeyword }}
{{# def.$data }}

{{## def.setExclusiveLimit:
$exclusive = true;
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
#}}
{{# def.numberKeyword }}

{{
var $isMax = $keyword == 'maximum'
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'
, $schemaExcl = it.schema[$exclusiveKeyword]
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
, $op = $isMax ? '<' : '>'
, $notOp = $isMax ? '>' : '<'
, $errorKeyword = undefined;

if (!($isData || typeof $schema == 'number' || $schema === undefined)) {
throw new Error($keyword + ' must be number');
}
if (!($isDataExcl || $schemaExcl === undefined
|| typeof $schemaExcl == 'number'
|| typeof $schemaExcl == 'boolean')) {
throw new Error($exclusiveKeyword + ' must be number or boolean');
var $op /* used in errors */, $notOp;
switch ($keyword) {
case 'maximum': $op = '<='; $notOp = '>'; break;
case 'minimum': $op = '>='; $notOp = '<'; break;
case 'exclusiveMaximum': $op = '<'; $notOp = '>='; break;
case 'exclusiveMinimum': $op = '>'; $notOp = '<='; break;
default: throw Error('not _limit keyword ' + $keyword);
}
}}

{{? $isDataExcl }}
{{
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
, $exclusive = 'exclusive' + $lvl
, $exclType = 'exclType' + $lvl
, $exclIsNumber = 'exclIsNumber' + $lvl
, $opExpr = 'op' + $lvl
, $opStr = '\' + ' + $opExpr + ' + \'';
}}
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}

var {{=$exclusive}};
var {{=$exclType}} = typeof {{=$schemaValueExcl}};
if ({{=$exclType}} != 'boolean' && {{=$exclType}} != 'undefined' && {{=$exclType}} != 'number') {
{{ var $errorKeyword = $exclusiveKeyword; }}
{{# def.error:'_exclusiveLimit' }}
} else if ({{# def.$dataNotType:'number' }}
{{=$exclType}} == 'number'
? (
({{=$exclusive}} = {{=$schemaValue}} === undefined || {{=$schemaValueExcl}} {{=$op}}= {{=$schemaValue}})
? {{=$data}} {{=$notOp}}= {{=$schemaValueExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
: (
({{=$exclusive}} = {{=$schemaValueExcl}} === true)
? {{=$data}} {{=$notOp}}= {{=$schemaValue}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
|| {{=$data}} !== {{=$data}}) {
var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
{{
if ($schema === undefined) {
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
$schemaValue = $schemaValueExcl;
$isData = $isDataExcl;
}
}}
{{??}}
{{
var $exclIsNumber = typeof $schemaExcl == 'number'
, $opStr = $op; /*used in error*/
}}

{{? $exclIsNumber && $isData }}
{{ var $opExpr = '\'' + $opStr + '\''; /*used in error*/ }}
if ({{# def.$dataNotType:'number' }}
( {{=$schemaValue}} === undefined
|| {{=$schemaExcl}} {{=$op}}= {{=$schemaValue}}
? {{=$data}} {{=$notOp}}= {{=$schemaExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}} )
|| {{=$data}} !== {{=$data}}) {
{{??}}
{{
if ($exclIsNumber && $schema === undefined) {
{{# def.setExclusiveLimit }}
$schemaValue = $schemaExcl;
$notOp += '=';
} else {
if ($exclIsNumber)
$schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);

if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
{{# def.setExclusiveLimit }}
$notOp += '=';
} else {
$exclusive = false;
$opStr += '=';
}
}

var $opExpr = '\'' + $opStr + '\''; /*used in error*/
}}

if ({{# def.$dataNotType:'number' }}
{{=$data}} {{=$notOp}} {{=$schemaValue}}
|| {{=$data}} !== {{=$data}}) {
{{?}}
{{?}}
{{ $errorKeyword = $errorKeyword || $keyword; }}
{{# def.error:'_limit' }}
} {{? $breakOnError }} else { {{?}}
if ({{# def.$dataNotType:'number' }} {{=$data}} {{=$notOp}} {{=$schemaValue}} || {{=$data}} !== {{=$data}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limit' }}
} {{? $breakOnError }} else { {{?}}
8 changes: 3 additions & 5 deletions lib/dot/errors.def
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@
'enum': "'should be equal to one of the allowed values'",
format: "'should match format \"{{#def.concatSchemaEQ}}\"'",
'if': "'should match \"' + {{=$ifClause}} + '\" schema'",
_limit: "'should be {{=$opStr}} {{#def.appendSchema}}",
_exclusiveLimit: "'{{=$exclusiveKeyword}} should be boolean'",
_limit: "'should be {{=$op}} {{#def.appendSchema}}",
_exclusiveLimit: "'should be {{=$op}} {{#def.appendSchema}}",
_limitItems: "'should NOT have {{?$keyword=='maxItems'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} items'",
_limitLength: "'should NOT be {{?$keyword=='maxLength'}}longer{{??}}shorter{{?}} than {{#def.concatSchema}} characters'",
_limitProperties:"'should NOT have {{?$keyword=='maxProperties'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} properties'",
Expand Down Expand Up @@ -139,7 +139,6 @@
format: "{{#def.schemaRefOrQS}}",
'if': "validate.schema{{=$schemaPath}}",
_limit: "{{#def.schemaRefOrVal}}",
_exclusiveLimit: "validate.schema{{=$schemaPath}}",
_limitItems: "{{#def.schemaRefOrVal}}",
_limitLength: "{{#def.schemaRefOrVal}}",
_limitProperties:"{{#def.schemaRefOrVal}}",
Expand Down Expand Up @@ -173,8 +172,7 @@
'enum': "{ allowedValues: schema{{=$lvl}} }",
format: "{ format: {{#def.schemaValueQS}} }",
'if': "{ failingKeyword: {{=$ifClause}} }",
_limit: "{ comparison: {{=$opExpr}}, limit: {{=$schemaValue}}, exclusive: {{=$exclusive}} }",
_exclusiveLimit: "{}",
_limit: "{ comparison: '{{=$op}}', limit: {{=$schemaValue}} }",
_limitItems: "{ limit: {{=$schemaValue}} }",
_limitLength: "{ limit: {{=$schemaValue}} }",
_limitProperties:"{ limit: {{=$schemaValue}} }",
Expand Down

0 comments on commit 6cede7b

Please sign in to comment.