Projekt

Obecné

Profil

Stáhnout (24.9 KB) Statistiky
| Větev: | Revize:
1 9bb1e829 cagy
# 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)