feat: keyword "nullable", #486, closes epoberezkin/ajv-keywords#32
parent
494026e44c
commit
f2010f40f2
|
@ -1029,6 +1029,7 @@ Defaults:
|
|||
jsonPointers: false,
|
||||
uniqueItems: true,
|
||||
unicode: true,
|
||||
nullable: false,
|
||||
format: 'fast',
|
||||
formats: {},
|
||||
unknownFormats: true,
|
||||
|
@ -1075,6 +1076,7 @@ Defaults:
|
|||
- _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.
|
||||
- _nullable_: support keyword "nullable" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).
|
||||
- _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.
|
||||
- _formats_: an object with custom formats. Keys and values will be passed to `addFormat` method.
|
||||
- _unknownFormats_: handling of unknown formats. Option values:
|
||||
|
|
|
@ -163,7 +163,8 @@ declare namespace ajv {
|
|||
sourceCode?: boolean;
|
||||
processCode?: (code: string) => string;
|
||||
cache?: object;
|
||||
logger?: CustomLogger | false
|
||||
logger?: CustomLogger | false;
|
||||
nullable?: boolean;
|
||||
}
|
||||
|
||||
type FormatValidator = string | RegExp | ((data: string) => boolean | PromiseLike<any>);
|
||||
|
|
|
@ -72,6 +72,7 @@ function Ajv(opts) {
|
|||
if (opts.formats) addInitialFormats(this);
|
||||
addDraft6MetaSchema(this);
|
||||
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
|
||||
if (opts.nullable) this.addKeyword('nullable', {metaSchema: {const: true}});
|
||||
addInitialSchemas(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,16 @@
|
|||
var $typeSchema = it.schema.type
|
||||
, $typeIsArray = Array.isArray($typeSchema);
|
||||
|
||||
if ($typeSchema && it.opts.nullable && it.schema.nullable === true) {
|
||||
if ($typeIsArray) {
|
||||
if ($typeSchema.indexOf('null') == -1)
|
||||
$typeSchema = $typeSchema.concat('null');
|
||||
} else if ($typeSchema != 'null') {
|
||||
$typeSchema = [$typeSchema, 'null'];
|
||||
$typeIsArray = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($typeIsArray && $typeSchema.length == 1) {
|
||||
$typeSchema = $typeSchema[0];
|
||||
$typeIsArray = false;
|
||||
|
|
|
@ -1412,4 +1412,91 @@ describe('Ajv Options', function () {
|
|||
}).should.throw(Error, /logger must implement log, warn and error methods/);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('nullable', function() {
|
||||
var ajv;
|
||||
|
||||
describe('= true', function() {
|
||||
beforeEach(function () {
|
||||
ajv = new Ajv({
|
||||
nullable: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should add keyword "nullable"', function() {
|
||||
testNullable({
|
||||
type: 'number',
|
||||
nullable: true
|
||||
});
|
||||
|
||||
testNullable({
|
||||
type: ['number'],
|
||||
nullable: true
|
||||
});
|
||||
|
||||
testNullable({
|
||||
type: ['number', 'null']
|
||||
});
|
||||
|
||||
testNullable({
|
||||
type: ['number', 'null'],
|
||||
nullable: true
|
||||
});
|
||||
|
||||
testNotNullable({type: 'number'});
|
||||
|
||||
testNotNullable({type: ['number']});
|
||||
});
|
||||
|
||||
it('"nullable" keyword must be "true" if present', function() {
|
||||
should.throw(function() {
|
||||
ajv.compile({nullable: false});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('without option "nullable"', function() {
|
||||
it('should ignore keyword nullable', function() {
|
||||
ajv = new Ajv;
|
||||
|
||||
testNotNullable({
|
||||
type: 'number',
|
||||
nullable: true
|
||||
});
|
||||
|
||||
testNotNullable({
|
||||
type: ['number'],
|
||||
nullable: true
|
||||
});
|
||||
|
||||
testNullable({
|
||||
type: ['number', 'null'],
|
||||
});
|
||||
|
||||
testNullable({
|
||||
type: ['number', 'null'],
|
||||
nullable: true
|
||||
});
|
||||
|
||||
should.not.throw(function () {
|
||||
ajv.compile({nullable: false});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function testNullable(schema) {
|
||||
var validate = ajv.compile(schema);
|
||||
validate(1) .should.equal(true);
|
||||
validate(null) .should.equal(true);
|
||||
validate('1') .should.equal(false);
|
||||
}
|
||||
|
||||
function testNotNullable(schema) {
|
||||
var validate = ajv.compile(schema);
|
||||
validate(1) .should.equal(true);
|
||||
validate(null) .should.equal(false);
|
||||
validate('1') .should.equal(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue