Projekt

Obecné

Profil

Stáhnout (24.9 KB) Statistiky
| Větev: | Revize:
1
# ajv-keywords
2

    
3
Custom JSON-Schema keywords for [Ajv](https://github.com/epoberezkin/ajv) validator
4

    
5
[![Build Status](https://travis-ci.org/epoberezkin/ajv-keywords.svg?branch=master)](https://travis-ci.org/epoberezkin/ajv-keywords)
6
[![npm](https://img.shields.io/npm/v/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
7
[![npm downloads](https://img.shields.io/npm/dm/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
8
[![Coverage Status](https://coveralls.io/repos/github/epoberezkin/ajv-keywords/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/ajv-keywords?branch=master)
9
[![Greenkeeper badge](https://badges.greenkeeper.io/epoberezkin/ajv-keywords.svg)](https://greenkeeper.io/)
10
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
11

    
12

    
13
## Contents
14

    
15
- [Install](#install)
16
- [Usage](#usage)
17
- [Keywords](#keywords)
18
  - [Types](#types)
19
    - [typeof](#typeof)
20
    - [instanceof](#instanceof)
21
  - [Keywords for numbers](#keywords-for-numbers)
22
    - [range and exclusiveRange](#range-and-exclusiverange)
23
  - [Keywords for strings](#keywords-for-strings)
24
    - [regexp](#regexp)
25
    - [formatMaximum / formatMinimum and formatExclusiveMaximum / formatExclusiveMinimum](#formatmaximum--formatminimum-and-formatexclusivemaximum--formatexclusiveminimum)
26
    - [transform](#transform)<sup>\*</sup>
27
  - [Keywords for arrays](#keywords-for-arrays)
28
    - [uniqueItemProperties](#uniqueitemproperties)
29
  - [Keywords for objects](#keywords-for-objects)
30
    - [allRequired](#allrequired)
31
    - [anyRequired](#anyrequired)
32
    - [oneRequired](#onerequired)
33
    - [patternRequired](#patternrequired)
34
    - [prohibited](#prohibited)
35
    - [deepProperties](#deepproperties)
36
    - [deepRequired](#deeprequired)
37
  - [Compound keywords](#compound-keywords)
38
    - [switch](#switch) (deprecated)
39
    - [select/selectCases/selectDefault](#selectselectcasesselectdefault) (BETA)
40
  - [Keywords for all types](#keywords-for-all-types)
41
    - [dynamicDefaults](#dynamicdefaults)<sup>\*</sup>
42
- [License](#license)
43

    
44
<sup>\*</sup> - keywords that modify data
45

    
46

    
47
## Install
48

    
49
```
50
npm install ajv-keywords
51
```
52

    
53

    
54
## Usage
55

    
56
To add all available keywords:
57

    
58
```javascript
59
var Ajv = require('ajv');
60
var ajv = new Ajv;
61
require('ajv-keywords')(ajv);
62

    
63
ajv.validate({ instanceof: 'RegExp' }, /.*/); // true
64
ajv.validate({ instanceof: 'RegExp' }, '.*'); // false
65
```
66

    
67
To add a single keyword:
68

    
69
```javascript
70
require('ajv-keywords')(ajv, 'instanceof');
71
```
72

    
73
To add multiple keywords:
74

    
75
```javascript
76
require('ajv-keywords')(ajv, ['typeof', 'instanceof']);
77
```
78

    
79
To add a single keyword in browser (to avoid adding unused code):
80

    
81
```javascript
82
require('ajv-keywords/keywords/instanceof')(ajv);
83
```
84

    
85

    
86
## Keywords
87

    
88
### Types
89

    
90
#### `typeof`
91

    
92
Based on JavaScript `typeof` operation.
93

    
94
The value of the keyword should be a string (`"undefined"`, `"string"`, `"number"`, `"object"`, `"function"`, `"boolean"` or `"symbol"`) or array of strings.
95

    
96
To pass validation the result of `typeof` operation on the value should be equal to the string (or one of the strings in the array).
97

    
98
```
99
ajv.validate({ typeof: 'undefined' }, undefined); // true
100
ajv.validate({ typeof: 'undefined' }, null); // false
101
ajv.validate({ typeof: ['undefined', 'object'] }, null); // true
102
```
103

    
104

    
105
#### `instanceof`
106

    
107
Based on JavaScript `instanceof` operation.
108

    
109
The value of the keyword should be a string (`"Object"`, `"Array"`, `"Function"`, `"Number"`, `"String"`, `"Date"`, `"RegExp"`, `"Promise"` or `"Buffer"`) or array of strings.
110

    
111
To pass validation the result of `data instanceof ...` operation on the value should be true:
112

    
113
```
114
ajv.validate({ instanceof: 'Array' }, []); // true
115
ajv.validate({ instanceof: 'Array' }, {}); // false
116
ajv.validate({ instanceof: ['Array', 'Function'] }, function(){}); // true
117
```
118

    
119
You can add your own constructor function to be recognised by this keyword:
120

    
121
```javascript
122
function MyClass() {}
123
var instanceofDefinition = require('ajv-keywords').get('instanceof').definition;
124
// or require('ajv-keywords/keywords/instanceof').definition;
125
instanceofDefinition.CONSTRUCTORS.MyClass = MyClass;
126

    
127
ajv.validate({ instanceof: 'MyClass' }, new MyClass); // true
128
```
129

    
130

    
131
### Keywords for numbers
132

    
133
#### `range` and `exclusiveRange`
134

    
135
Syntax sugar for the combination of minimum and maximum keywords, also fails schema compilation if there are no numbers in the range.
136

    
137
The value of this keyword must be the array consisting of two numbers, the second must be greater or equal than the first one.
138

    
139
If the validated value is not a number the validation passes, otherwise to pass validation the value should be greater (or equal) than the first number and smaller (or equal) than the second number in the array. If `exclusiveRange` keyword is present in the same schema and its value is true, the validated value must not be equal to the range boundaries.
140

    
141
```javascript
142
var schema = { range: [1, 3] };
143
ajv.validate(schema, 1); // true
144
ajv.validate(schema, 2); // true
145
ajv.validate(schema, 3); // true
146
ajv.validate(schema, 0.99); // false
147
ajv.validate(schema, 3.01); // false
148

    
149
var schema = { range: [1, 3], exclusiveRange: true };
150
ajv.validate(schema, 1.01); // true
151
ajv.validate(schema, 2); // true
152
ajv.validate(schema, 2.99); // true
153
ajv.validate(schema, 1); // false
154
ajv.validate(schema, 3); // false
155
```
156

    
157

    
158
### Keywords for strings
159

    
160
#### `regexp`
161

    
162
This keyword allows to use regular expressions with flags in schemas (the standard `pattern` keyword does not support flags).
163

    
164
This keyword applies only to strings. If the data is not a string, the validation succeeds.
165

    
166
The value of this keyword can be either a string (the result of `regexp.toString()`) or an object with the properties `pattern` and `flags` (the same strings that should be passed to RegExp constructor).
167

    
168
```javascript
169
var schema = {
170
  type: 'object',
171
  properties: {
172
    foo: { regexp: '/foo/i' },
173
    bar: { regexp: { pattern: 'bar', flags: 'i' } }
174
  }
175
};
176

    
177
var validData = {
178
  foo: 'Food',
179
  bar: 'Barmen'
180
};
181

    
182
var invalidData = {
183
  foo: 'fog',
184
  bar: 'bad'
185
};
186
```
187

    
188

    
189
#### `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum`
190

    
191
These keywords allow to define minimum/maximum constraints when the format keyword defines ordering.
192

    
193
These keywords apply only to strings. If the data is not a string, the validation succeeds.
194

    
195
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. If `format` is not present schema compilation will throw exception.
196

    
197
When this keyword is added, it defines comparison rules for formats `"date"`, `"time"` and `"date-time"`. Custom formats also can have comparison rules. See [addFormat](https://github.com/epoberezkin/ajv#api-addformat) method.
198

    
199
The value of keyword `formatExclusiveMaximum` (`formatExclusiveMinimum`) should be a boolean value. These keyword cannot be used without `formatMaximum` (`formatMinimum`). If this keyword value is equal to `true`, the data to be valid should not be equal to the value in `formatMaximum` (`formatMinimum`) keyword.
200

    
201
```javascript
202
require('ajv-keywords')(ajv, ['formatMinimum', 'formatMaximum']);
203

    
204
var schema = {
205
  format: 'date',
206
  formatMinimum: '2016-02-06',
207
  formatMaximum: '2016-12-27',
208
  formatExclusiveMaximum: true
209
}
210

    
211
var validDataList = ['2016-02-06', '2016-12-26', 1];
212

    
213
var invalidDataList = ['2016-02-05', '2016-12-27', 'abc'];
214
```
215

    
216

    
217
#### `transform`
218

    
219
This keyword allows a string to be modified before validation. 
220

    
221
These keywords apply only to strings. If the data is not a string, the transform is skipped.
222

    
223
There are limitation due to how ajv is written:
224
- a stand alone string cannot be transformed. ie `data = 'a'; ajv.validate(schema, data);`
225
- currently cannot work with `ajv-pack`
226

    
227
**Supported options:**
228
- `trim`: remove whitespace from start and end
229
- `trimLeft`: remove whitespace from start
230
- `trimRight`: remove whitespace from end
231
- `toLowerCase`: case string to all lower case
232
- `toUpperCase`: case string to all upper case
233
- `toEnumCase`: case string to match case in schema
234

    
235
Options are applied in the order they are listed.
236

    
237
Note: `toEnumCase` requires that all allowed values are unique when case insensitive.
238

    
239
**Example: multiple options**
240
```javascript
241
require('ajv-keywords')(ajv, ['transform']);
242

    
243
var schema = {
244
  type: 'array',
245
  items: {
246
    type:'string',
247
    transform:['trim','toLowerCase']
248
  }
249
};
250

    
251
var data = ['  MixCase  '];
252
ajv.validate(schema, data);
253
console.log(data); // ['mixcase']
254

    
255
```
256

    
257
**Example: `enumcase`**
258
```javascript
259
require('ajv-keywords')(ajv, ['transform']);
260

    
261
var schema = {
262
  type: 'array',
263
  items: {
264
    type:'string',
265
    transform:['trim','toEnumCase'],
266
    enum:['pH']
267
  }
268
};
269

    
270
var data = ['ph',' Ph','PH','pH '];
271
ajv.validate(schema, data);
272
console.log(data); // ['pH','pH','pH','pH']
273
```
274

    
275

    
276
### Keywords for arrays
277

    
278
#### `uniqueItemProperties`
279

    
280
The keyword allows to check that some properties in array items are unique.
281

    
282
This keyword applies only to arrays. If the data is not an array, the validation succeeds.
283

    
284
The value of this keyword must be an array of strings - property names that should have unique values across all items.
285

    
286
```javascript
287
var schema = { uniqueItemProperties: [ "id", "name" ] };
288

    
289
var validData = [
290
  { id: 1 },
291
  { id: 2 },
292
  { id: 3 }
293
];
294

    
295
var invalidData1 = [
296
  { id: 1 },
297
  { id: 1 }, // duplicate "id"
298
  { id: 3 }
299
];
300

    
301
var invalidData2 = [
302
  { id: 1, name: "taco" },
303
  { id: 2, name: "taco" }, // duplicate "name"
304
  { id: 3, name: "salsa" }
305
];
306
```
307

    
308
This keyword is contributed by [@blainesch](https://github.com/blainesch).
309

    
310

    
311
### Keywords for objects
312

    
313
#### `allRequired`
314

    
315
This keyword allows to require the presence of all properties used in `properties` keyword in the same schema object.
316

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

    
319
The value of this keyword must be boolean.
320

    
321
If the value of the keyword is `false`, the validation succeeds.
322

    
323
If the value of the keyword is `true`, the validation succeeds if the data contains all properties defined in `properties` keyword (in the same schema object).
324

    
325
If the `properties` keyword is not present in the same schema object, schema compilation will throw exception.
326

    
327
```javascript
328
var schema = {
329
  properties: {
330
    foo: {type: 'number'},
331
    bar: {type: 'number'}
332
  }
333
  allRequired: true
334
};
335

    
336
var validData = { foo: 1, bar: 2 };
337
var alsoValidData = { foo: 1, bar: 2, baz: 3 };
338

    
339
var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
340
```
341

    
342

    
343
#### `anyRequired`
344

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

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

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

    
351
```javascript
352
var schema = {
353
  anyRequired: ['foo', 'bar']
354
};
355

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

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

    
362

    
363
#### `oneRequired`
364

    
365
This keyword allows to require the presence of only one property from the list.
366

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

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

    
371
```javascript
372
var schema = {
373
  oneRequired: ['foo', 'bar']
374
};
375

    
376
var validData = { foo: 1 };
377
var alsoValidData = { bar: 2, baz: 3 };
378

    
379
var invalidDataList = [ {}, { baz: 3 }, { foo: 1, bar: 2 } ];
380
```
381

    
382

    
383
#### `patternRequired`
384

    
385
This keyword allows to require the presence of properties that match some pattern(s).
386

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

    
389
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.
390

    
391
If the array contains multiple regular expressions, more than one expression can match the same property name.
392

    
393
```javascript
394
var schema = { patternRequired: [ 'f.*o', 'b.*r' ] };
395

    
396
var validData = { foo: 1, bar: 2 };
397
var alsoValidData = { foobar: 3 };
398

    
399
var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
400
```
401

    
402

    
403
#### `prohibited`
404

    
405
This keyword allows to prohibit that any of the properties in the list is present in the object.
406

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

    
409
The value of this keyword should be an array of strings, each string being a property name. For data object to be valid none of the properties in this array should be present in the object.
410

    
411
```
412
var schema = { prohibited: ['foo', 'bar']};
413

    
414
var validData = { baz: 1 };
415
var alsoValidData = {};
416

    
417
var invalidDataList = [
418
  { foo: 1 },
419
  { bar: 2 },
420
  { foo: 1, bar: 2}
421
];
422
```
423

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

    
426

    
427
#### `deepProperties`
428

    
429
This keyword allows to validate deep properties (identified by JSON pointers).
430

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

    
433
The value should be an object, where keys are JSON pointers to the data, starting from the current position in data, and the values are JSON schemas. For data object to be valid the value of each JSON pointer should be valid according to the corresponding schema.
434

    
435
```javascript
436
var schema = {
437
  type: 'object',
438
  deepProperties: {
439
    "/users/1/role": { "enum": ["admin"] }
440
  }
441
};
442

    
443
var validData = {
444
  users: [
445
    {},
446
    {
447
      id: 123,
448
      role: 'admin'
449
    }
450
  ]
451
};
452

    
453
var alsoValidData = {
454
  users: {
455
    "1": {
456
      id: 123,
457
      role: 'admin'
458
    }
459
  }
460
};
461

    
462
var invalidData = {
463
  users: [
464
    {},
465
    {
466
      id: 123,
467
      role: 'user'
468
    }
469
  ]
470
};
471

    
472
var alsoInvalidData = {
473
  users: {
474
    "1": {
475
      id: 123,
476
      role: 'user'
477
    }
478
  }
479
};
480
```
481

    
482

    
483
#### `deepRequired`
484

    
485
This keyword allows to check that some deep properties (identified by JSON pointers) are available.
486

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

    
489
The value should be an array of JSON pointers to the data, starting from the current position in data. For data object to be valid each JSON pointer should be some existing part of the data.
490

    
491
```javascript
492
var schema = {
493
  type: 'object',
494
  deepRequired: ["/users/1/role"]
495
};
496

    
497
var validData = {
498
  users: [
499
    {},
500
    {
501
      id: 123,
502
      role: 'admin'
503
    }
504
  ]
505
};
506

    
507
var invalidData = {
508
  users: [
509
    {},
510
    {
511
      id: 123
512
    }
513
  ]
514
};
515
```
516

    
517
See [json-schema-org/json-schema-spec#203](https://github.com/json-schema-org/json-schema-spec/issues/203#issue-197211916) for an example of the equivalent schema without `deepRequired` keyword.
518

    
519

    
520
### Compound keywords
521

    
522
#### `switch` (deprecated)
523

    
524
__Please note__: this keyword is provided to preserve backward compatibility with previous versions of Ajv. It is strongly recommended to use `if`/`then`/`else` keywords instead, as they have been added to the draft-07 of JSON Schema specification.
525

    
526
This keyword allows to perform advanced conditional validation.
527

    
528
The value of the keyword is the array of if/then clauses. Each clause is the object with the following properties:
529

    
530
- `if` (optional) - the value is JSON-schema
531
- `then` (required) - the value is JSON-schema or boolean
532
- `continue` (optional) - the value is boolean
533

    
534
The validation process is dynamic; all clauses are executed sequentially in the following way:
535

    
536
1. `if`:
537
    1.  `if` property is JSON-schema according to which the data is:
538
        1.  valid => go to step 2.
539
        2.  invalid => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
540
    2.  `if` property is absent => go to step 2.
541
2. `then`:
542
    1.  `then` property is `true` or it is JSON-schema according to which the data is valid => go to step 3.
543
    2.  `then` property is `false` or it is JSON-schema according to which the data is invalid => the validation of `switch` FAILS.
544
3. `continue`:
545
    1.  `continue` property is `true` => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
546
    2.  `continue` property is `false` or absent => validation of `switch` SUCCEEDS.
547

    
548
```javascript
549
require('ajv-keywords')(ajv, 'switch');
550

    
551
var schema = {
552
  type: 'array',
553
  items: {
554
    type: 'integer',
555
    'switch': [
556
      { if: { not: { minimum: 1 } }, then: false },
557
      { if: { maximum: 10 }, then: true },
558
      { if: { maximum: 100 }, then: { multipleOf: 10 } },
559
      { if: { maximum: 1000 }, then: { multipleOf: 100 } },
560
      { then: false }
561
    ]
562
  }
563
};
564

    
565
var validItems = [1, 5, 10, 20, 50, 100, 200, 500, 1000];
566

    
567
var invalidItems = [1, 0, 2000, 11, 57, 123, 'foo'];
568
```
569

    
570
The above schema is equivalent to (for example):
571

    
572
```javascript
573
{
574
  type: 'array',
575
  items: {
576
    type: 'integer',
577
    if: { minimum: 1, maximum: 10 },
578
    then: true,
579
    else: {
580
      if: { maximum: 100 },
581
      then: { multipleOf: 10 },
582
      else: {
583
        if: { maximum: 1000 },
584
        then: { multipleOf: 100 },
585
        else: false
586
      }
587
    }
588
  }
589
}
590
```
591

    
592

    
593
#### `select`/`selectCases`/`selectDefault`
594

    
595
These keywords allow to choose the schema to validate the data based on the value of some property in the validated data.
596

    
597
These keywords must be present in the same schema object (`selectDefault` is optional).
598

    
599
The value of `select` keyword should be a [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference) that points to any primitive JSON type (string, number, boolean or null) in the data that is validated. You can also use a constant of primitive type as the value of this keyword (e.g., for debugging purposes).
600

    
601
The value of `selectCases` keyword must be an object where each property name is a possible string representation of the value of `select` keyword and each property value is a corresponding schema (from draft-06 it can be boolean) that must be used to validate the data.
602

    
603
The value of `selectDefault` keyword is a schema (from draft-06 it can be boolean) that must be used to validate the data in case `selectCases` has no key equal to the stringified value of `select` keyword.
604

    
605
The validation succeeds in one of the following cases:
606
- the validation of data using selected schema succeeds,
607
- none of the schemas is selected for validation,
608
- the value of select is undefined (no property in the data that the data reference points to).
609

    
610
If `select` value (in data) is not a primitive type the validation fails.
611

    
612
__Please note__: these keywords require Ajv `$data` option to support [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference).
613

    
614

    
615
```javascript
616
require('ajv-keywords')(ajv, 'select');
617

    
618
var schema = {
619
  type: object,
620
  required: ['kind'],
621
  properties: {
622
    kind: { type: 'string' }
623
  },
624
  select: { $data: '0/kind' },
625
  selectCases: {
626
    foo: {
627
      required: ['foo'],
628
      properties: {
629
        kind: {},
630
        foo: { type: 'string' }
631
      },
632
      additionalProperties: false
633
    },
634
    bar: {
635
      required: ['bar'],
636
      properties: {
637
        kind: {},
638
        bar: { type: 'number' }
639
      },
640
      additionalProperties: false
641
    }
642
  },
643
  selectDefault: {
644
    propertyNames: {
645
      not: { enum: ['foo', 'bar'] }
646
    }
647
  }
648
};
649

    
650
var validDataList = [
651
  { kind: 'foo', foo: 'any' },
652
  { kind: 'bar', bar: 1 },
653
  { kind: 'anything_else', not_bar_or_foo: 'any value' }
654
];
655

    
656
var invalidDataList = [
657
  { kind: 'foo' }, // no propery foo
658
  { kind: 'bar' }, // no propery bar
659
  { kind: 'foo', foo: 'any', another: 'any value' }, // additional property
660
  { kind: 'bar', bar: 1, another: 'any value' }, // additional property
661
  { kind: 'anything_else', foo: 'any' } // property foo not allowed
662
  { kind: 'anything_else', bar: 1 } // property bar not allowed
663
];
664
```
665

    
666
__Please note__: the current implementation is BETA. It does not allow using relative URIs in $ref keywords in schemas in `selectCases` and `selectDefault` that point outside of these schemas. The workaround is to use absolute URIs (that can point to any (sub-)schema added to Ajv, including those inside the current root schema where `select` is used). See [tests](https://github.com/epoberezkin/ajv-keywords/blob/v2.0.0/spec/tests/select.json#L314).
667

    
668

    
669
### Keywords for all types
670

    
671
#### `dynamicDefaults`
672

    
673
This keyword allows to assign dynamic defaults to properties, such as timestamps, unique IDs etc.
674

    
675
This keyword only works if `useDefaults` options is used and not inside `anyOf` keywords etc., in the same way as [default keyword treated by Ajv](https://github.com/epoberezkin/ajv#assigning-defaults).
676

    
677
The keyword should be added on the object level. Its value should be an object with each property corresponding to a property name, in the same way as in standard `properties` keyword. The value of each property can be:
678

    
679
- an identifier of default function (a string)
680
- an object with properties `func` (an identifier) and `args` (an object with parameters that will be passed to this function during schema compilation - see examples).
681

    
682
The properties used in `dynamicDefaults` should not be added to `required` keyword (or validation will fail), because unlike `default` this keyword is processed after validation.
683

    
684
There are several predefined dynamic default functions:
685

    
686
- `"timestamp"` - current timestamp in milliseconds
687
- `"datetime"` - current date and time as string (ISO, valid according to `date-time` format)
688
- `"date"` - current date as string (ISO, valid according to `date` format)
689
- `"time"` - current time as string (ISO, valid according to `time` format)
690
- `"random"` - pseudo-random number in [0, 1) interval
691
- `"randomint"` - pseudo-random integer number. If string is used as a property value, the function will randomly return 0 or 1. If object `{ func: 'randomint', args: { max: N } }` is used then the default will be an integer number in [0, N) interval.
692
- `"seq"` - sequential integer number starting from 0. If string is used as a property value, the default sequence will be used. If object `{ func: 'seq', args: { name: 'foo'} }` is used then the sequence with name `"foo"` will be used. Sequences are global, even if different ajv instances are used.
693

    
694
```javascript
695
var schema = {
696
  type: 'object',
697
  dynamicDefaults: {
698
    ts: 'datetime',
699
    r: { func: 'randomint', args: { max: 100 } },
700
    id: { func: 'seq', args: { name: 'id' } }
701
  },
702
  properties: {
703
    ts: {
704
      type: 'string',
705
      format: 'date-time'
706
    },
707
    r: {
708
      type: 'integer',
709
      minimum: 0,
710
      exclusiveMaximum: 100
711
    },
712
    id: {
713
      type: 'integer',
714
      minimum: 0
715
    }
716
  }
717
};
718

    
719
var data = {};
720
ajv.validate(data); // true
721
data; // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 }
722

    
723
var data1 = {};
724
ajv.validate(data1); // true
725
data1; // { ts: '2016-12-01T22:07:29.832Z', r: 68, id: 1 }
726

    
727
ajv.validate(data1); // true
728
data1; // didn't change, as all properties were defined
729
```
730

    
731
When using the `useDefaults` option value `"empty"`, properties and items equal to `null` or `""` (empty string) will be considered missing and assigned defaults.  Use the `allOf` [compound keyword](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#compound-keywords) to execute `dynamicDefaults` before validation.
732

    
733
```javascript
734
var schema = {
735
  allOf: [
736
    {
737
      dynamicDefaults: {
738
        ts: 'datetime',
739
        r: { func: 'randomint', args: { min: 5, max: 100 } },
740
        id: { func: 'seq', args: { name: 'id' } }
741
      }
742
    },
743
    {
744
      type: 'object',
745
      properties: {
746
        ts: {
747
          type: 'string'
748
        },
749
        r: {
750
          type: 'number',
751
          minimum: 5,
752
          exclusiveMaximum: 100
753
        },
754
        id: {
755
          type: 'integer',
756
          minimum: 0
757
        }
758
      }
759
    }
760
  ]
761
};
762

    
763
var data = { ts: '', r: null };
764
ajv.validate(data); // true
765
data; // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 }
766
```
767

    
768
You can add your own dynamic default function to be recognised by this keyword:
769

    
770
```javascript
771
var uuid = require('uuid');
772

    
773
function uuidV4() { return uuid.v4(); }
774

    
775
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
776
// or require('ajv-keywords/keywords/dynamicDefaults').definition;
777
definition.DEFAULTS.uuid = uuidV4;
778

    
779
var schema = {
780
  dynamicDefaults: { id: 'uuid' },
781
  properties: { id: { type: 'string', format: 'uuid' } }
782
};
783

    
784
var data = {};
785
ajv.validate(schema, data); // true
786
data; // { id: 'a1183fbe-697b-4030-9bcc-cfeb282a9150' };
787

    
788
var data1 = {};
789
ajv.validate(schema, data1); // true
790
data1; // { id: '5b008de7-1669-467a-a5c6-70fa244d7209' }
791
```
792

    
793
You also can define dynamic default that accepts parameters, e.g. version of uuid:
794

    
795
```javascript
796
var uuid = require('uuid');
797

    
798
function getUuid(args) {
799
  var version = 'v' + (arvs && args.v || 4);
800
  return function() {
801
    return uuid[version]();
802
  };
803
}
804

    
805
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
806
definition.DEFAULTS.uuid = getUuid;
807

    
808
var schema = {
809
  dynamicDefaults: {
810
    id1: 'uuid', // v4
811
    id2: { func: 'uuid', v: 4 }, // v4
812
    id3: { func: 'uuid', v: 1 } // v1
813
  }
814
};
815
```
816

    
817

    
818
## License
819

    
820
[MIT](https://github.com/epoberezkin/ajv-keywords/blob/master/LICENSE)
(2-2/4)