Skip to content

Commit

Permalink
feat: keyword "nullable", #486, closes ajv-validator/ajv-keywords#32
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Nov 10, 2018
1 parent 494026e commit f2010f4
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ Defaults:
jsonPointers: false,
uniqueItems: true,
unicode: true,
nullable: false,
format: 'fast',
formats: {},
unknownFormats: true,
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion lib/ajv.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>);
Expand Down
1 change: 1 addition & 0 deletions lib/ajv.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
10 changes: 10 additions & 0 deletions lib/dot/validate.jst
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
87 changes: 87 additions & 0 deletions spec/options.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});
});

0 comments on commit f2010f4

Please sign in to comment.