1
|
# ajv-errors
|
2
|
Custom error messages in JSON-Schema for Ajv validator
|
3
|
|
4
|
[![Build Status](https://travis-ci.org/epoberezkin/ajv-errors.svg?branch=master)](https://travis-ci.org/epoberezkin/ajv-errors)
|
5
|
[![npm version](https://badge.fury.io/js/ajv-errors.svg)](http://badge.fury.io/js/ajv-errors)
|
6
|
[![Coverage Status](https://coveralls.io/repos/github/epoberezkin/ajv-errors/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/ajv-errors?branch=master)
|
7
|
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
|
8
|
|
9
|
|
10
|
## Contents
|
11
|
|
12
|
- [Install](#install)
|
13
|
- [Usage](#usage)
|
14
|
- [Single message](#single-message)
|
15
|
- [Messages for keywords](#messages-for-keywords)
|
16
|
- [Messages for properties and items](#messages-for-properties-and-items)
|
17
|
- [Default message](#default-message)
|
18
|
- [Templates](#templates)
|
19
|
- [Options](#options)
|
20
|
- [License](#license)
|
21
|
|
22
|
|
23
|
## Install
|
24
|
|
25
|
```
|
26
|
npm install ajv-errors
|
27
|
```
|
28
|
|
29
|
|
30
|
## Usage
|
31
|
|
32
|
Add the keyword `errorMessages` to Ajv instance:
|
33
|
|
34
|
```javascript
|
35
|
var Ajv = require('ajv');
|
36
|
var ajv = new Ajv({allErrors: true, jsonPointers: true});
|
37
|
// Ajv options allErrors and jsonPointers are required
|
38
|
require('ajv-errors')(ajv /*, {singleError: true} */);
|
39
|
```
|
40
|
|
41
|
See [Options](#options) below.
|
42
|
|
43
|
|
44
|
### Single message
|
45
|
|
46
|
Replace all errors in the current schema and subschemas with a single message:
|
47
|
|
48
|
```javascript
|
49
|
var schema = {
|
50
|
type: 'object',
|
51
|
required: ['foo'],
|
52
|
properties: {
|
53
|
foo: { type: 'integer' }
|
54
|
},
|
55
|
additionalProperties: false,
|
56
|
errorMessage: 'should be an object with an integer property foo only'
|
57
|
};
|
58
|
|
59
|
var validate = ajv.compile(schema);
|
60
|
console.log(validate({foo: 'a', bar: 2})); // false
|
61
|
console.log(validate.errors); // processed errors
|
62
|
```
|
63
|
|
64
|
Processed errors:
|
65
|
|
66
|
```javascript
|
67
|
[
|
68
|
{
|
69
|
keyword: 'errorMessage',
|
70
|
message: 'should be an object with an integer property foo only',
|
71
|
// ...
|
72
|
params: {
|
73
|
errors: [
|
74
|
{ keyword: 'additionalProperties', dataPath: '' /* , ... */ },
|
75
|
{ keyword: 'type', dataPath: '.foo' /* , ... */ }
|
76
|
]
|
77
|
}
|
78
|
}
|
79
|
]
|
80
|
```
|
81
|
|
82
|
|
83
|
### Messages for keywords
|
84
|
|
85
|
Replace errors for certain keywords in the current schema only:
|
86
|
|
87
|
```javascript
|
88
|
var schema = {
|
89
|
type: 'object',
|
90
|
required: ['foo'],
|
91
|
properties: {
|
92
|
foo: { type: 'integer' }
|
93
|
},
|
94
|
additionalProperties: false,
|
95
|
errorMessage: {
|
96
|
type: 'should be an object', // will not replace internal "type" error for the property "foo"
|
97
|
required: 'should have property foo',
|
98
|
additionalProperties: 'should not have properties other than foo'
|
99
|
}
|
100
|
};
|
101
|
|
102
|
var validate = ajv.compile(schema);
|
103
|
console.log(validate({foo: 'a', bar: 2})); // false
|
104
|
console.log(validate.errors); // processed errors
|
105
|
```
|
106
|
|
107
|
Processed errors:
|
108
|
|
109
|
```javascript
|
110
|
[
|
111
|
{
|
112
|
// original error
|
113
|
keyword: type,
|
114
|
dataPath: '/foo',
|
115
|
// ...
|
116
|
message: 'should be integer'
|
117
|
},
|
118
|
{
|
119
|
// generated error
|
120
|
keyword: 'errorMessage',
|
121
|
message: 'should not have properties other than foo',
|
122
|
// ...
|
123
|
params: {
|
124
|
errors: [
|
125
|
{ keyword: 'additionalProperties' /* , ... */ }
|
126
|
]
|
127
|
},
|
128
|
}
|
129
|
]
|
130
|
```
|
131
|
|
132
|
For keywords "required" and "dependencies" it is possible to specify different messages for different properties:
|
133
|
|
134
|
```javascript
|
135
|
var schema = {
|
136
|
type: 'object',
|
137
|
required: ['foo', 'bar'],
|
138
|
properties: {
|
139
|
foo: { type: 'integer' },
|
140
|
bar: { type: 'string' }
|
141
|
},
|
142
|
errorMessage: {
|
143
|
type: 'should be an object', // will not replace internal "type" error for the property "foo"
|
144
|
required: {
|
145
|
foo: 'should have an integer property "foo"',
|
146
|
bar: 'should have a string property "bar"'
|
147
|
}
|
148
|
}
|
149
|
};
|
150
|
```
|
151
|
|
152
|
|
153
|
### Messages for properties and items
|
154
|
|
155
|
Replace errors for properties / items (and deeper), regardless where in schema they were created:
|
156
|
|
157
|
```javascript
|
158
|
var schema = {
|
159
|
type: 'object',
|
160
|
required: ['foo', 'bar'],
|
161
|
allOf: [{
|
162
|
properties: {
|
163
|
foo: { type: 'integer', minimum: 2 },
|
164
|
bar: { type: 'string', minLength: 2 }
|
165
|
},
|
166
|
additionalProperties: false
|
167
|
}],
|
168
|
errorMessage: {
|
169
|
properties: {
|
170
|
foo: 'data.foo should be integer >= 2',
|
171
|
bar: 'data.bar should be string with length >= 2'
|
172
|
}
|
173
|
}
|
174
|
};
|
175
|
|
176
|
var validate = ajv.compile(schema);
|
177
|
console.log(validate({foo: 1, bar: 'a'})); // false
|
178
|
console.log(validate.errors); // processed errors
|
179
|
```
|
180
|
|
181
|
Processed errors:
|
182
|
|
183
|
```javascript
|
184
|
[
|
185
|
{
|
186
|
keyword: 'errorMessage',
|
187
|
message: 'data.foo should be integer >= 2',
|
188
|
dataPath: '/foo',
|
189
|
// ...
|
190
|
params: {
|
191
|
errors: [
|
192
|
{ keyword: 'minimum' /* , ... */ }
|
193
|
]
|
194
|
},
|
195
|
},
|
196
|
{
|
197
|
keyword: 'errorMessage',
|
198
|
message: 'data.bar should be string with length >= 2',
|
199
|
dataPath: '/bar',
|
200
|
// ...
|
201
|
params: {
|
202
|
errors: [
|
203
|
{ keyword: 'minLength' /* , ... */ }
|
204
|
]
|
205
|
},
|
206
|
}
|
207
|
]
|
208
|
```
|
209
|
|
210
|
|
211
|
### Default message
|
212
|
|
213
|
When the value of keyword `errorMessage` is an object you can specify a message that will be used if any error appears that is not specified by keywords/properties/items:
|
214
|
|
215
|
```javascript
|
216
|
var schema = {
|
217
|
type: 'object',
|
218
|
required: ['foo', 'bar'],
|
219
|
allOf: [{
|
220
|
properties: {
|
221
|
foo: { type: 'integer', minimum: 2 },
|
222
|
bar: { type: 'string', minLength: 2 }
|
223
|
},
|
224
|
additionalProperties: false
|
225
|
}],
|
226
|
errorMessage: {
|
227
|
type: 'data should be an object',
|
228
|
properties: {
|
229
|
foo: 'data.foo should be integer >= 2',
|
230
|
bar: 'data.bar should be string with length >= 2'
|
231
|
},
|
232
|
_: 'data should have properties "foo" and "bar" only'
|
233
|
}
|
234
|
};
|
235
|
|
236
|
var validate = ajv.compile(schema);
|
237
|
console.log(validate({})); // false
|
238
|
console.log(validate.errors); // processed errors
|
239
|
```
|
240
|
|
241
|
Processed errors:
|
242
|
|
243
|
```javascript
|
244
|
[
|
245
|
{
|
246
|
keyword: 'errorMessage',
|
247
|
message: 'data should be an object with properties "foo" and "bar" only',
|
248
|
dataPath: '',
|
249
|
// ...
|
250
|
params: {
|
251
|
errors: [
|
252
|
{ keyword: 'required' /* , ... */ },
|
253
|
{ keyword: 'required' /* , ... */ }
|
254
|
]
|
255
|
},
|
256
|
}
|
257
|
]
|
258
|
```
|
259
|
|
260
|
The message in property `_` of `errorMessage` replaces the same errors that would have been replaced if `errorMessage` were a string.
|
261
|
|
262
|
|
263
|
## Templates
|
264
|
|
265
|
Custom error messages used in `errorMessage` keyword can be templates using [JSON-pointers](https://tools.ietf.org/html/rfc6901) or [relative JSON-pointers](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00) to data being validated, in which case the value will be interpolated. Also see [examples](https://gist.github.com/geraintluff/5911303) of relative JSON-pointers.
|
266
|
|
267
|
The syntax to interpolate a value is `${<pointer>}`.
|
268
|
|
269
|
The values used in messages will be JSON-stringified:
|
270
|
- to differentiate between `false` and `"false"`, etc.
|
271
|
- to support structured values.
|
272
|
|
273
|
Example:
|
274
|
|
275
|
```json
|
276
|
{
|
277
|
"type": "object",
|
278
|
"properties": {
|
279
|
"size": {
|
280
|
"type": "number",
|
281
|
"minimum": 4
|
282
|
}
|
283
|
},
|
284
|
"errorMessage": {
|
285
|
"properties": {
|
286
|
"size": "size should be a number bigger or equal to 4, current value is ${/size}"
|
287
|
}
|
288
|
}
|
289
|
}
|
290
|
```
|
291
|
|
292
|
|
293
|
## Options
|
294
|
|
295
|
Defaults:
|
296
|
|
297
|
```javascript
|
298
|
{
|
299
|
keepErrors: false,
|
300
|
singleError: false
|
301
|
}
|
302
|
```
|
303
|
|
304
|
- _keepErrors_: keep original errors. Default is to remove matched errors (they will still be available in `params.errors` property of generated error). If an error was matched and included in the error generated by `errorMessage` keyword it will have property `emUsed: true`.
|
305
|
- _singleError_: create one error for all keywords used in `errorMessage` keyword (error messages defined for properties and items are not merged because they have different dataPaths). Multiple error messages are concatenated. Option values:
|
306
|
- `false` (default): create multiple errors, one for each message
|
307
|
- `true`: create single error, messages are concatenated using `"; "`
|
308
|
- non-empty string: this string is used as a separator to concatenate messages
|
309
|
|
310
|
|
311
|
## Supporters
|
312
|
|
313
|
[<img src="https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAwEAAAAJDg1YzBlYzFjLTA3YWYtNGEzOS1iMTdjLTQ0MTU1NWZjOGM0ZQ.jpg" width="48" height="48">](https://www.linkedin.com/in/rogerkepler/) [Roger Kepler](https://www.linkedin.com/in/rogerkepler/)
|
314
|
|
315
|
|
316
|
## License
|
317
|
|
318
|
[MIT](https://github.com/epoberezkin/ajv-errors/blob/master/LICENSE)
|