1# ajv-errors
2Custom 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```
26npm install ajv-errors
27```
28
29
30## Usage
31
32Add the keyword `errorMessages` to Ajv instance:
33
34```javascript
35var Ajv = require('ajv');
36var ajv = new Ajv({allErrors: true, jsonPointers: true});
37// Ajv options allErrors and jsonPointers are required
38require('ajv-errors')(ajv /*, {singleError: true} */);
39```
40
41See [Options](#options) below.
42
43
44### Single message
45
46Replace all errors in the current schema and subschemas with a single message:
47
48```javascript
49var 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
59var validate = ajv.compile(schema);
60console.log(validate({foo: 'a', bar: 2})); // false
61console.log(validate.errors); // processed errors
62```
63
64Processed 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
85Replace errors for certain keywords in the current schema only:
86
87```javascript
88var 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
102var validate = ajv.compile(schema);
103console.log(validate({foo: 'a', bar: 2})); // false
104console.log(validate.errors); // processed errors
105```
106
107Processed 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
132For keywords "required" and "dependencies" it is possible to specify different messages for different properties:
133
134```javascript
135var 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
155Replace errors for properties / items (and deeper), regardless where in schema they were created:
156
157```javascript
158var 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
176var validate = ajv.compile(schema);
177console.log(validate({foo: 1, bar: 'a'})); // false
178console.log(validate.errors); // processed errors
179```
180
181Processed 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
213When 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
216var 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
236var validate = ajv.compile(schema);
237console.log(validate({})); // false
238console.log(validate.errors); // processed errors
239```
240
241Processed 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
260The message in property `_` of `errorMessage` replaces the same errors that would have been replaced if `errorMessage` were a string.
261
262
263## Templates
264
265Custom 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
267The syntax to interpolate a value is `${<pointer>}`.
268
269The values used in messages will be JSON-stringified:
270- to differentiate between `false` and `"false"`, etc.
271- to support structured values.
272
273Example:
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
295Defaults:
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## License
312
313[MIT](https://github.com/epoberezkin/ajv-errors/blob/master/LICENSE)
314