ajv-validator / ajv-errors Goto Github PK
View Code? Open in Web Editor NEWCustom error messages in JSON Schemas for Ajv validator
Home Page: https://ajv.js.org
License: MIT License
Custom error messages in JSON Schemas for Ajv validator
Home Page: https://ajv.js.org
License: MIT License
"Messages for keywords" says that I can pass a single string value for a keyword
errorMessage: { required: 'field is required.' }
But doing so throws an error saying that "data.properties['errorMessage'].required" expects an array rather than a string.
Also, keyword error message does not seem to work because the error message is just a plain JSON validation error message.
Expected:
{ keyword: 'required', dataPath: '', schemaPath: '#/required', params: { missingProperty: 'someField' }, message: 'field is required.'' } ]
Actual:
{ keyword: 'required', dataPath: '', schemaPath: '#/required', params: { missingProperty: 'someField' }, message: 'should have required property \'someField\'' } ]
schema is invalid: data/properties/errorMessage/additionalProperties should be object,boolean, data/properties/errorMessage/type should be equal to one of the allowed values, data/properties/errorMessage/type should be array, data/properties/errorMessage/type should match some schema in anyOf
Hello all,
I'm trying to use ajv-errors with my jsonforms to implement custom error messages. After wrapping my ajv instance in an ajv-errors instance I am receiving the following error:
Error: node_modules/ajv-errors/dist/index.d.ts:1:15 - error TS2305: Module '"ajv"' has no exported member 'Plugin'.
I've run npm install ajv-errors, I wasn't aware of any other dependencies that should be added. If you could take a look I'd appreciate it, thanks.
{
type: 'object',
required: ['foo', 'bar'],
errorMessages: {
type: 'should be an object',
required: {
foo: 'property foo must be present',
bar: 'property bar is required'
}
}
}
If the message is present for the required property that is not specified in required keyword a warning should be logged during schema compilation.
Hello! 👋 Firstly, I wanted to thank you for this amazing library (and ajv, of course) :)
I'm facing an issue where I want to have a templated error message in a subschema, but its JSON pointers are referencing the parent schema. Here's what I wanted to do:
const schema = {
type: 'object',
properties: {
parcels: {
type: 'array',
minItems: 1,
items: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' }
errorMessage: {
properties: {
id: '${/name} was not found'
}
}
}
}
},
errorMessage: {
properties: {
parcels: 'you need to add at least one parcel'
}
}
};
const ajv = new Ajv({ allErrors: true, jsonPointers: true });
AjvErrors(ajv);
const validate = ajv.compile(schema);
const valid = validate({
items: [{ id: null, name: 'parcel-1' }]
});
// Expected result: validate.errors[0].message === "parcel-1 was not found"
// Actual result: validate.errors[0].message === "undefined was not found"
Is there an actual way to achieve this behaviour? Thanks in advance!
Default will stay "replace"
Errors should be marked to avoid being used twice
I ran vue create client
but when i try npm run serve
I get the error below.
- Building for production...
ERROR Error: custom keyword definition is invalid: data.errors should be boolean
Error: custom keyword definition is invalid: data.errors should be boolean
at Ajv.addKeyword (/Users/bocaops/Code/fullstack_vue_express/client/node_modules/ajv/lib/keyword.js:65:13)
at module.exports (/Users/bocaops/Code/fullstack_vue_express/client/node_modules/ajv-errors/index.js:10:7)
at Object.<anonymous> (/Users/bocaops/Code/fullstack_vue_express/client/node_modules/schema-utils/src/validateOptions.js:22:1)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:20:18)
Total task duration: 1.1s```
Hi!
I've tried including everything that is needed to resolve this. Let me know if something is missing or if I can help!
Code:
JSON-Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$async": true,
"type": "object",
"properties": {
"title": {
"type": "string",
"errorMessage": "this is an error message"
}
}
}
Code
const ajv = new Ajv({ allErrors: true });
ajvErrors(ajv);
ajv.addSchema(TEST_SCHEMA, "test");
await ajv.validate('test', 'somedata');
Error:
Error compiling schema, function code: const Error0 = scope.Error[0];const schema16 = scope.schema[10];return async function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){let vErrors = null;let errors = 0;if(data && typeof data == "object" && !Array.isArray(data)){if(data.title !== undefined){if(typeof data.title !== "string"){const err0 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(errors > 0){for(const err1 of vErrors){if((((({"str":"err1"}.keyword !== "errorMessage") && (!{"str":"err1"}.emUsed)) && (({"str":"err1"}.instancePath === instancePath+{"_items":["\"/title\""]}) || (({"str":"err1"}.instancePath.indexOf(instancePath+{"_items":["\"/title\""]}) === 0) && ({"str":"err1"}.instancePath[instancePath+{"_items":["\"/title\""]}.length] === "/")))) && ({"str":"err1"}.schemaPath.indexOf("#/properties/title") === 0)) && ({"str":"err1"}.schemaPath["#/properties/title".length] === "/")){{"str":"emErrs0"}.push({"str":"err1"});{"str":"err1"}.emUsed = true;}}if({"str":"emErrs0"}.length){if(vErrors === null){vErrors = [{"str":"err2"}];}else {vErrors.push({"str":"err2"});}errors++;}const emErrs1 = [];for(const err3 of vErrors){if(!{"str":"err3"}.emUsed){{"str":"emErrs1"}.push({"str":"err3"});}}vErrors = emErrs1;errors = {"str":"emErrs1"}.length;}}}else {const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(errors === 0){return data;}else {throw new Error0(vErrors);}}
...
SyntaxError: Unexpected token ':'
Seems like some of the generated code is not correct?
Particularly; these snippets which are repeated multiple times.:
{"str":"emErrs0"}.push({"str":"err1"});
// ...
{"str":"err1"}.emUsed = true;
Maybe it's something in my environment?
Running node 14.16.0.
ajv 8.1.0
ajv-errors 3.0.0
Suggestions?
var schema = {
type: 'object',
required: ['foo', 'bar'],
errorMessage: {
required: {
foo: 'missing foo property',
bar: 'missing bar property'
}
}
Processed errors:
[
{
keyword: 'errorMessage',
message: 'missing foo property',
dataPath: '',
// ...
},
{
keyword: 'errorMessage',
message: 'missing bar property',
dataPath: '',
// ...
}
]
It is difficult to know which error message was generated for which property.
It is needed for automatic processing.
Now there are two possible workarounds:
Suggestion:
Add name of missing property to dataPath. This is possible only when property specific message is defined.
Another suggestion:
Add option allowing to have separate messages for missing properties (even if single error message is defined for all missing properties). This would allow to have correct dataPath settings for every missing property.
Tested the following combinations:
Good day, I have observed a strange behavior when using ajv-errors
with singleError
flag turned on. Honestly, I can't remember why even it was turned on in my code but when I turn it off, this unexpected behavior stops.
The code below is the minimum reproducible example for the issue I am describing. I had a fairly complex schema but I have simplified to the most basic example I could to illustrate the issue.
When I have two errorMessage
properties, set as follows - one in the top level and the other in one of the fields, an extraneous empty error is reported.
(In my case there were a lot more).
I hope you'd shed some light on this unexpected behavior. Many thanks!
const AJV = require('ajv').default;
const ajvErrors = require('ajv-errors');
const validator = new AJV({ allErrors: true});
// Add AJV errors with singleError: true
ajvErrors(validator, {
singleError:true
});
validator.addSchema({
$id: 'pizzaOrder',
type:'object',
additionalProperties: false,
errorMessage:{
additionalProperties:'Pizza order is invalid'
},
properties:{
price:{
type:'number'
},
toppings:{
type:'object',
additionalProperties: false,
errorMessage: {
_: 'Unsupported topping'
},
properties: {
pineapple:{
type: 'boolean'
}
}
}
}
});
validator.validate('pizzaOrder', {
somethingBad: true,
toppings:{
pineapple:true
}
});
console.log(JSON.stringify(validator.errors, null, 2));;
Since I have deliberately put an additionalProperty
called somethingBad
I would expect it to be reported as follows:
[
{
"keyword": "errorMessage",
"dataPath": "",
"schemaPath": "#/errorMessage",
"params": {
"errors": [
{
"keyword": "additionalProperties",
"dataPath": "",
"schemaPath": "#/additionalProperties",
"params": {
"additionalProperty": "somethingBad"
},
"message": "should NOT have additional properties",
"emUsed": true
}
]
},
"message": "Pizza order is invalid"
}
]
But actually, as highlighted below, there's an extra error that creeps in with an empty message and empty params.errors
for toppings
which actually is totally valid.
[
+ {
+ "keyword": "errorMessage",
+ "dataPath": "/toppings",
+ "schemaPath": "#/properties/toppings/errorMessage",
+ "params": {
+ "errors": []
+ },
+ "message": ""
+ },
{
"keyword": "errorMessage",
"dataPath": "",
"schemaPath": "#/errorMessage",
"params": {
"errors": [
{
"keyword": "additionalProperties",
"dataPath": "",
"schemaPath": "#/additionalProperties",
"params": {
"additionalProperty": "somethingBad"
},
"message": "should NOT have additional properties",
"emUsed": true
}
]
},
"message": "Pizza order is invalid"
}
]
Currently I have turned of singleError
completely, hopefully it won't affect my other schema's error reports
ajvErrors(validator, {
- singleError:true // removed
});
Another thing I have noticed, which may aid finding the issue is that when I did changed the schema this way:
{
$id: 'pizzaOrder',
type:'object',
additionalProperties: false,
errorMessage:{
additionalProperties:'Pizza order is invalid'
},
properties:{
price:{
type:'number'
},
toppings:{
type:'object',
additionalProperties: false,
- errorMessage: {
- _: 'Unsupported topping'
- },
+ errorMessage: 'Unsupported topping'
properties: {
pineapple:{
type: 'boolean'
}
}
}
}
}
The problem went away too. In my case it's not possible however, since I have other error keyword in my full example.
Let me know if any clarifications are required
Similar to #13, is there a way catch the error in the if schema so that only it gets reported. The only way to catch the if-clause seems to be a top-level errorMessage on if
, however this then gets report if the then schema fails as well. Placing an errorMessage
in the if
schema appears to do nothing.
This could just be a matter of me not knowing how to "throw" an error other than with else: false
.
const Ajv = require("ajv");
const ajv = new Ajv({
"allErrors": true,
"jsonPointers": true
});
require('ajv-errors')(ajv);
const schema = {
"type":"object",
"properties": {
"foo": {
"type":"string",
"if":{
"maxLength":5
},
"then":{
"enum":["bar"],
"errorMessage":{
"enum":"then-clause failed"
}
},
"else":false,
"errorMessage":{
"if":"if-clause failed."
}
}
}
}
let validate = ajv.compile(schema);
console.log(validate({"foo":"baz"}));
console.log("Errors:",ajv.errorsText(validate.errors));
https://runkit.com/jerdak/keyword-error-for-if-clause-failure
Prints "Errors: data/foo then-clause failed', data/foo if-clause failed."
Ideally I would like to customize the error for the if
failure without having to double check the maxLength
, once for the if
schema and once at the property schema level.
Hi!
Thanks for your great libraries. It's cool to work with.
Being able to define the key for the error messages could be nice.
maybe something like:
import Ajv from 'ajv'
import ajvErrors from 'ajv-errors'
let ajv = new Ajv({ allErrors: true })
ajv = ajvErrors(ajv, { keyword: "myCustomErrorMessage" })
what is your opinion about that?
thank for all!
Hello,
I have a schema like this :
{
type: 'object',
required: ['mail'],
properties: {
mail: {
type: 'string',
format: 'email',
errorMessage: 'INVALID_MAIL'
}
},
errorMessage: {
required: {
mail: 'MISSING_MAIL'
}
}
}
When validation fails, the returned error will either be body MISSING_MAIL
or body/mail INVALID_MAIL
.
I would just like to have my custom message and only my custom message, which is either MISSING_MAIL
or INVALID_MAIL
, to be returned.
Thanks
Hi,
I have a simple schema
{
"name": "getOrdersQuerySchema",
"$id": "getOrdersQuerySchema",
"type": "object",
"properties": {
"skip": {
"type": "number",
"minimum": 0
},
"sort": {
"type": "string"
},
"recipient.reference": {
"type": "string"
}
},
"additionalProperties": false,
"errorMessage": {
"additionalProperties": "The allowed searchable fields are ...."
}
}
When I validate this with an property not defined in the schema (e.g foo) I get the error data/foo is an invalid additional property
I was expecting to see The allowed searchable fields are ....
Am I missing something? Interestingly if i do :
"errorMessage": "A generic error message."
Then it works.
Hello.
How can i get value and field which cause validation error in errors object?
Here's mine scheme
{
"type": "object",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"position": {
"type": "number"
},
"shifts": {
"type": "object",
"required": ["0", "1", "2", "3"],
"properties": {
"0": { "type": "boolean" },
"1": { "type": "boolean" },
"2": { "type": "boolean" },
"3": { "type": "boolean" }
},
"errorMessage": {
"required": {
"0": "Parameter \"morning_shift\" is not provided!",
"1": "Parameter \"noon_shift\" is not provided!",
"2": "Parameter \"evening_shift\" is not provided!",
"3": "Parameter \"night_shift\" is not provided!"
},
"additionalProperties": "Shifts should not contains additional properties!"
},
"additionalProperties": false
},
"jumper": {
"type": "number"
},
"manager": {
"type": "number"
}
},
"required": [
"first_name",
"last_name",
"email",
"position",
"shifts",
"jumper",
"manager"
],
"errorMessage": {
"required": {
"first_name": "Parameter \"first_name\" is not provided!",
"last_name": "Parameter \"first_name\" is not provided!",
"email": "Parameter \"first_name\" is not provided!",
"position": "Parameter \"first_name\" is not provided!",
"shifts": "Parameter \"shifts\" is not provided!",
"jumper": "Parameter \"jumper_unit\" is not provided!",
"manager": "Parameter \"manager_unit\" is not provided!"
},
"properties": {
"first_name": "First name is invalid, given \"${/first_name}!\"",
"last_name": "Last name is invalid, given \"${/last_name}!\"",
"email": "Email name is invalid, given \"${/email}!\"",
"position": "Position is invalid, given \"${/position}!\"",
"shifts": "Shifts is invalid, given \"${/shifts}!\"",
"jumper": "Jumper is invalid, given \"${/jumper}!\"",
"manager": "Manager is invalid, given \"${/manager}!\""
},
"additionalProperties": "File should not contains additional properties!"
},
"additionalProperties": false
}
Depend on response, error contains dataPath
, message
and in verbose mode data
fields.
What i need is the real field name which cause error, and real value which this field has.
I it's not provided then i need only field name.
Is there any way to get it, or to put it in errors?
Here's my kinda fake data for showing errors:
[
{
"first_name": "Hello 1",
"last_name": "World 1",
"position": 111,
"jumper": "131",
"shifts": {
"0": true,
"1": true,
"2": false
}
},
{
"first_name": "Hello 2",
"last_name": "World 2",
"position": 131090,
"jumper": "131103",
"shifts": {
"0": true,
"1": true,
"2": true
}
}
]
Thank you.
"ajv": "^7.0.0-beta.4",
"ajv-errors": "^2.0.0-beta.0",
const ajv = new Ajv({ allErrors: true })
require('ajv-errors')(ajv)
[email protected]
[email protected]
[email protected]
Hi when I was trying belowed case I got a ReferenceError: data1 is not defined
from my node. It seems that ajv's scheme compiler generates wrong code. When I change schema.foo.bar
's type definition or reduce the nesting levels the same error will not occurred again.
const Ajv = require('ajv');
const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
const schema = {
type: "object",
properties: {
foo: {
type: "object",
properties: {
bar: {
type: "string",
errorMessage: "${0}",
},
},
},
},
};
const data = {
foo: {
bar: false,
},
};
ajv.validate(schema, data);
console.log(ajv.errors);
Sincerely hope for replying.
default will be multiple still
What version of Ajv are you using?
using ajv 7.1.1 and ajv-errors 2.0.0
Your code
const schema = {
type: "object",
properties: {
foo: {type: "integer", minimum: 2}
},
errorMessage: {
properties: {
foo: "data.foo should be integer >= 2"
}
}
}
const Ajv = require("ajv").default
const ajv = new Ajv({code: {source: true}, allErrors: true})
const standaloneCode = require("ajv/dist/standalone").default
require('ajv-errors')(ajv)
const validate = ajv.compile(schema);
let moduleCode = standaloneCode(ajv, validate)
const fs = require("fs")
const path = require("path")
fs.writeFileSync(path.join(__dirname, 'schema.js'), moduleCode);
error message
node_modules\ajv\dist\compile\codegen\scope.js:134
throw new ValueError(name);
^
ValueError: CodeGen: "code" for pattern0 not defined
What results did you expect?
this kind of schema is still documented in ajv-errors 2.0.0 documentation, so i expected standalone code to be generated for that schema but seems not
I'm just thinking ahead on what will be on the roadmap, and this popped to mind.
What is the best approach to providing custom errors in multiple languages? Is it even possible right now? Something planned for when ajv-i18n become a proper plugin?
Probably using null
as the value of errorMessage
When errorMessage is an object, one of the properties can be "_"
- it should contain a custom message that will be added for all other errors, not caught by keyword- and property/item-specific message.
Hey :) First of all, thank you for this amazing library.
I was wondering if it is possible to use params in custom errors templates ?
For example, I'd like to be able to do something like this:
errorMessage: {
additionalProperties: 'Invalid additional property "${params.additionalProperty}"'
}
To get an error message with the property that failed.
Is there anyway to do it or do we have to post-process the error ?
Thanks !
Hi,
I want to use ajv errors in JSONforms react(typescript) app. I have defined the errorMessage in the schema. But it always showing the generated messages instead of custom messages
`import Ajv from 'ajv';
import AjvErrors from 'ajv-errors';
const ajv = new Ajv({ allErrors: true, jsonPointers: true });
const AjvConfig = AjvErrors(ajv);
export default AjvConfig;`
Thanks
schema:
{
"title":"",
"type":"object",
"properties":{
"file_url":{
"type":"object",
"properties":{
}
},
"delay_type":{
"type":"object",
"properties":{
"name":{
"type":"string"
},
"key":{
"type":"string"
}
},
"required":[
],
"keys":[
"delay_type"
]
},
"hold_zwh_time":{
"type":"string"
},
"join_book_url":{
"type":"object",
"properties":{
}
},
"reward_type":{
"type":"object",
"properties":{
"name":{
"type":"string"
},
"key":{
"type":"string"
}
},
"required":[
],
"keys":[
"reward_type"
]
},
"join_oath_date_url":{
"type":"object",
"properties":{
}
},
"join_oath_date":{
"type":"string"
},
"committee_file_url":{
"type":"string"
},
"superior_party_committee_date":{
"type":"string"
},
"other_time":{
"type":"string"
}
},
"required":[
"hold_zwh_time",
"superior_party_committee_date",
"join_oath_date",
"reward_type",
"delay_type",
"other_time"
],
"$id":"ccp_develop_positive_delay",
"errorMessage":{
"type":"object",
"required":{
"other_time":"error tip"
}
}
}
model:
{"file_url":{},"join_book_url":{},"join_oath_date_url":{},"reward_type":{"name":"yc","key":"14"},"delay_type":{"name":"other","key":"2","parent":"-1"}}
const ajv = new ajvErrors(Ajv({ allErrors: true, jsonPointers: true, useDefaults: true }));
const validator = ajv.compile(schema);
const valid = validator(model);
if (!valid) {
......
}
when execute script like this chrome 70 will block and crash!
I am using ajv validation from browser. By adding the following code in the HTML page.
<script src="js/ajv.min.js"></script>Is there any way or possible to use ajv-errors in the HTML page. I had tried to use by the following default in the html page. But it is not working.
var ajv = new Ajv({allErrors: true}); // options can be passed, e.g. {allErrors: true}
var schemaForRegCheck ={
"type": "number",
"minimum": 10,
"additionalProperties": false,
"errorMessage": 'this is a custom error messages'
}
Thank you advance.
Hey everybody,
I have some issues when i'm trying to put errorMessage with an array, for example, this is my schema :
"pictures": {
"type": "array",
"items": {
"type": "string",
"pattern": "A_SPECIFIC_PATTERN_TO_PUT_HERE"
},
"errorMessage": {
"type": "INVALID_MEDIA_PICTURES_ITEMS",
}
},
When the pattern doesn't match, I don't receive errorMessage keyword, but instead :
error {
keyword: 'pattern',
dataPath: '/media/pictures/0',
schemaPath: 'media-schema.json/properties/pictures/items/pattern',
params: {
pattern: 'A_SPECIFIC_PATTERN_TO_PUT_HERE'
},
message: 'should match pattern A_SPECIFIC_PATTERN_TO_PUT_HERE'
}
I would like to receive my INVALID_MEDIA_PICTURES_ITEMS
. I have the feeling errorMessage only works with type: object
Am I missing something here ?
Hi, I am working on a feature where I want to show a list of the errors generated by the validator and provide a filter functionality to filter errors based on some identifier. Is it possible to add some kind of identifier to the errors?
code sandbox:
https://codesandbox.io/s/friendly-boyd-c2qtm?file=/src/index.ts
The bellow schema returns the correct error message for minLength when it is defined on the parent or child prop, but it returns the default error when defined on an array property.
import Ajv from "ajv";
import ajvErrors from "ajv-errors";
export function validate<T>(values: T, validationSchema: object) {
const ajv = new Ajv({ allErrors: true });
ajvErrors(ajv);
const validate = ajv.compile(validationSchema);
validate(values);
console.log(...validate.errors);
}
const SCHEMA = {
type: "object",
required: ["parent", "child", "arr"],
errorMessage: {
properties: {
parent: "parent custom length error ***111"
}
},
properties: {
parent: {
type: "string",
minLength: 5
},
arr: {
type: "array",
items: {
type: "object",
required: ["arrayProp"],
errorMessage: {
required:"custom required array prop",
properties: {
arrayProp: "arrayProp custom length error ***333 "
}
},
properties: {
arrayProp: {
type: "string",
minLength: 5
}
}
}
},
child: {
type: "object",
required: ["childProp"],
errorMessage: {
properties: {
childProp: "childProp custom length error ***222"
}
},
properties: {
childProp: {
type: "string",
minLength: 5
}
}
}
}
};
const DATA = {
parent: "aaaa",
child: {
childProp: "aaaa"
},
arr: [
{
arrayProp: "aaaa"
}
]
};
validate(DATA, SCHEMA);
these are the results:
{instancePath: "/arr/0/arrayProp", schemaPath: "#/properties/arr/items/properties/arrayProp/minLength", keyword: "minLength", params: Object, message: "must NOT have fewer than 5 characters"}
{instancePath: "/child/childProp", schemaPath: "#/properties/child/errorMessage", keyword: "errorMessage", params: Object, message: "childProp custom length error ***222"}
{instancePath: "/parent", schemaPath: "#/errorMessage", keyword: "errorMessage", params: Object, message: "parent custom length error ***111"}
If i write so
var Ajv = require('ajv');
var ajv = new Ajv({allErrors: true, jsonPointers: true});
require('ajv-errors')(ajv);
var data = {}
var valid = ajv.validate({
'required': ['p1', 'p2'],
'errorMessage': {
'required': {
'p1': 'some p1 error',
'p2': 'some p2 error'
}
}
}, data);
if (!valid) console.log(ajv.errors);
all work. If so
var Ajv = require('ajv');
var ajv = new Ajv({allErrors: true, jsonPointers: true});
require('ajv-errors')(ajv);
var data = {}
var valid = ajv.validate({
'required': ['p1', 'p2'],
'errorMessage': {
'required': {
'p1': 'some p1 error'
}
}
}, data);
if (!valid) console.log(ajv.errors);
script stops.
node: 8.4.0
Including type: 'integer'
When ajv-validator/ajv#485 is resolved
Hi,
I have the following code
//AJV Setup
let ajv = require('ajv);
ajv = new Ajv({
allErrors: true,
v5: true,
jsonPointers: true
});
require('ajv-keywords')(ajv);
require('ajv-errors')(ajv);
//validation schema
let required1 = ['foo'];
let required2 = required1.concat(['bar']);
schema = {
"type": "object",
"properties" : {
"foo": { "type": "string" },
"bar": { "type": "string" },
"published" : boolean
},
"switch": [
{
"if": { "properties": { "published": {"enum": [false, undefined]} } },
"then": { "required": required1 },
},
{
"if": { "properties": { "published": {"constant": true} } },
"then": { "required": required2 },
}
],
"errorMessage": {
required: {
"foo": "foo should be present"
}
}
}
//JS Call
let validate = ajv.compile(schema);
validate({foo: null, bar: null, published: false}); //returns false as expected
console.log(validate.errors);
The expected output as per what I could understand from the documentation was to be
[ { keyword: 'errorMessage',
dataPath: '',
schemaPath: '#/errorMessage',
params: [Object],
message: 'foo should be present' } ]
But I am getting the following error and the custom error message is not showing up
//console output -- actual
[ { keyword: 'required',
dataPath: '.foo',
schemaPath: '#/switch/1/then/required',
params: [Object],
message: '.foo should have required property \'foo\'' } ]
{
error:{
obj:"Hey"
}
}
upto best of my knowledge i guess it should thorw an error as Json should be like
{
"error":{
"obj":"Hey"
}
}
will be waiting for your reply.
Is there any way where one can add custom error message for pathPattern attributes? Example:
Json schema:
"patternProperties": {
"^[a-zA-Z0-9]*$":{
"properties": {
"model":{"type":"string"},
"made":{"type":"string"},
"year":{"type":"string"}
}
}
},
"additionalProperties":false
}
Json:
{
"efgh56789": {
"model": "civic"
"made": "toyota"
"year": "2014"
}
}
Here, how to add custom error message (ex: Can contain only alphanumeric characters) for the attribute 'efgh56789' in above schema?
Note: The schema can be a nested schema where few of them are 'patternProperties' & few of them are regular ones.
I have asked the same question in SoF:
Ref: link
A bug with uri-js package has been fixed in ajv, but this lib doesn't use the latest ajv version and isn't using the latest version, and is therefore failing during compiling when using create-react-app.
Publishing a new version of jv-error-messages based on the lastest 6.x ajv version should fix this.
Hello I have written type definitions for this library:
https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ajv-errors
Have a nice one!
Hello,
First of all, thank you for this library, and also for the main ajv
library! :) I would just like to post this in order to save other people a few hours.
I discovered yesterday that it is important to add your keywords to your ajv instance before adding this ajv-errors
plugin. Otherwise, customized error messages for your custom keywords will not appear, as your validators have not run by the time this plugin goes looking for custom error messages.
Example - if you init this plugin before adding your keywords:
const ajv = require('ajv')
const instance = new ajv({
allErrors: true,
jsonPointers: true
})
require('ajv-errors')(instance)
instance.addKeyword('testError', {
validate: () => false
})
const validator = instance.compile({
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://workflow.rlscplatform.net/PPB_ASSAY",
"type": "object",
"properties": {
"test": {
"type": "string",
"testError": true,
"errorMessage": {
"testError": "This is my custom error message"
}
}
}
})
validator({
test: "test"
})
console.log(validator.errors)
Outputs this:
[ { keyword: 'testError',
dataPath: '/test',
schemaPath: '#/properties/test/testError',
params: { keyword: 'testError' },
message: 'should pass "testError" keyword validation' } ]
But if you just put ajv-errors after your addKeyword:
instance.addKeyword('testError', {
validate: () => false
})
require('ajv-errors')(instance)
The output becomes:
[ { keyword: 'errorMessage',
dataPath: '/test',
schemaPath: '#/properties/test/errorMessage',
params: { errors: [Array] },
message: 'This is my custom error message' } ]
Regards,
TJ
{
type: 'object',
allOf: [{
properties: {
foo: {
type: 'object',
anyOf: [
{
required: ['bar'],
properties: { bar: { type: 'integer' } },
additionalProperties: false
},
{
required: ['baz'],
properties: { baz: { type: 'string' } },
additionalProperties: false
}
]
}
}
}],
errorMessages: {
type: 'should be object',
properties: {
foo: 'foo should be an object with an integer property "bar" (only) or with a string property "baz" (only)'
}
}
}
All errors for property foo
should be replaced with a single error with provided message, even though properties is inside "allOf" and errors are in sub-children - only data path is matched, not the location in schema.
Hi I am trying to use this ajv-errors package with react and typescript but I keep getting this error even though allErrors is set true? my code is as follows:
`import Ajv, { JSONSchemaType } from 'ajv'
import addFormats from 'ajv-formats'
import ajvErrors from 'ajv-errors'
const ajv = new Ajv({ allErrors: true, $data: true })
ajvErrors(addFormats(ajv))
export const emailSchema: JSONSchemaType = {
type: 'string',
minLength: 1,
format: 'email',
errorMessage: 'test',
}
export const passwordSchema: JSONSchemaType = {
type: 'string',
minLength: 12,
maxLength: 100,
pattern: '(?=.\d)(?=.[a-z])(?=.[A-Z])(?=.\W)',
errorMessage: 'test',
}
export const recaptchaTockenSchema: JSONSchemaType = {
type: 'string',
minLength: 1,
errorMessage: 'test',
}
const passwordValidator = ajv.compile(passwordSchema)
const emailValidator = ajv.compile(emailSchema)
export const validatePassword = (value: string) => {
return {
isValid: passwordValidator(value),
error: passwordValidator.errors ? passwordValidator.errors[0]?.message : '',
}
}
export const validateEmail = (value: string) => {
return {
isValid: emailValidator(value),
error: emailValidator.errors ? emailValidator.errors[0]?.message : '',
}
}`
Hello,
I had this error with my webpack build:
/srv/http/elabftw/node_modules/webpack-cli/bin/cli.js:231
throw err;
^
Error: custom keyword definition is invalid: data/errors should be boolean
at Ajv.addKeyword (/srv/http/elabftw/node_modules/ajv/lib/keyword.js:65:13)
at module.exports (/srv/http/elabftw/node_modules/ajv-errors/index.js:10:7)
at Object.<anonymous> (/srv/http/elabftw/node_modules/schema-utils/src/validateOptions.js:22:1)
at Module._compile (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at Module.require (internal/modules/cjs/loader.js:663:17)
at require (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
at Object.<anonymous> (/srv/http/elabftw/node_modules/schema-utils/src/index.js:7:25)
at Module._compile (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at Module.require (internal/modules/cjs/loader.js:663:17)
at require (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
at Object.<anonymous> (/srv/http/elabftw/node_modules/webpack/lib/SourceMapDevToolPlugin.js:13:25)
at Module._compile (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at Module.require (internal/modules/cjs/loader.js:663:17)
at require (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
at Object.<anonymous> (/srv/http/elabftw/node_modules/webpack/lib/WebpackOptionsApply.js:16:32)
at Module._compile (/srv/http/elabftw/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
error Command failed with exit code 1.
Changing line 14 of index.js and setting it errors
to true
fixed the issue. But I'm not sure of the consequences, I just know it lets me build my files :)
Do you think a fix could be published for this issue? I'm using 1.0.1 of ajv-errors and latest versions of wepack and friends.
I have the following schema and json to validate using ajv. I am developing a REST API that takes a JSON and gets validated against the schema and it returns the error (400- with the ajv error) or (200 - when successfully validated)
//Assuming ajv, ajv-errors npm are installed properly
const schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [ "countries" ],
"definitions": {
"europeDef": {
"type": "object",
"required": ["type"],
"properties": { "type": {"const": "europe"} }
},
"errorMessage":"Country type should be europe only"
"asiaDef": {
"type": "object",
"required": ["type"],
"properties": { "type": {"const": "asia"} }
},
"errorMessage":"Country type should be asia only"
},
"properties": {
"countries": {
"type": "array",
"items": {
"oneOf":[
{ "$ref": "#/definitions/europeDef" },
{ "$ref": "#/definitions/asiaDef"}
]
}
}
}
}
const data = {
"countries":[
{"type": "asia1"},
{"type": "europe"}
]
}
const isValid = ajv.validate(schema, data); //schema, data
if(! isValid){
console.log(ajv.errors);
}
and the error is:
[
{
keyword: 'errorMessage',
dataPath: '/countries/1',
schemaPath: '#/definitions/europeDef/errorMessage',
params: { errors: [Array] },
message: 'Country type should be europe only'
},
{
keyword: 'errorMessage',
dataPath: '/countries/1',
schemaPath: '#/definitions/asiaDef/errorMessage',
params: { errors: [Array] },
message: 'Country type should be asia only'
},
{
keyword: 'oneOf',
dataPath: '/countries/1',
schemaPath: '#/properties/countries/items/oneOf',
params: { passingSchemas: null },
message: 'should match exactly one schema in oneOf'
}
]
I know why the error is appearing (reason: as I have used 'asia1' and it is not conforming the schema standard). Here, the problem is with "asia", but the ajv is giving the error mesage for 'europe' too (despite it is correct)
My question is, as I have derived this schema so I can pretty much understand the error. But for a third person it would definitely take some time to figure it out (and it may take more time, if the schema/errors are more complex).
If I returned that whole error message as a response as it is, it will be more complex error message to understand and to present to the enduser.
So, Is there any way by which I can provide more meaningful & user friendly/specific error message to understand using this ajv-errors npm? I tried but not able to make it possible using this npm.
ex: Invalid asia1 found for country type found.
P.S: Originally asked at SoF: Link and slightly updated for this issue in this git repo.
[email protected]
[email protected]
Greets,
I have included schema and simple test case below showing that a default error message does not produce consistent results. For some reason the "nested" oneOf statement w/ default error message produces two entries in the errors
output. The oneOf statement at the top level which is exactly the same produces one entry in the errors
output.
IE for the schema below the entry count with the default error message should be the same for both failing validation cases:
{ system: [false] }
and { packs: [{ system: [false] }] }
The latter is not picking up the child items type error in the default error message which is part of the oneOf block.
const Ajv = require("ajv").default;
const ajv = new Ajv({ allErrors: true });
// Ajv option allErrors is required
require("ajv-errors")(ajv);
const schema = {
$id: "test",
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
packs: {
type: "array",
items: {
type: "object",
properties: {
system: {
oneOf: [
{ type: "string" },
{
items: { type: "string" },
type: "array"
}
],
errorMessage: "should be a string or array of strings"
}
}
}
},
system: {
oneOf: [
{ type: "string" },
{
items: { type: "string" },
type: "array"
}
],
errorMessage: "should be a string or array of strings"
}
}
};
const validate = ajv.compile(schema);
// Expect `errorMessage` to catch all errors at or below the oneOf level.
console.log(`{ system: [false] }:`);
console.log(JSON.stringify(validate.errors, null, 3));
// Expect `errorMessage` to catch all errors at or below the oneOf level.
// However it does not catch the further items type and there are two errors.
console.log('\n-------------------------------------------------------------\n');
console.log(`expect only one error in 'errors', but there are two for { packs: [{ system: [false] }] }:`);
console.log(JSON.stringify(validate.errors, null, 3));
#Output:
{ system: [false] }:
[
{
"keyword": "errorMessage",
"dataPath": "/system",
"schemaPath": "#/properties/system/errorMessage",
"params": {
"errors": [
{
"keyword": "type",
"dataPath": "/system",
"schemaPath": "#/properties/system/oneOf/0/type",
"params": {
"type": "string"
},
"message": "should be string",
"emUsed": true
},
{
"keyword": "type",
"dataPath": "/system/0",
"schemaPath": "#/properties/system/oneOf/1/items/type",
"params": {
"type": "string"
},
"message": "should be string",
"emUsed": true
},
{
"keyword": "oneOf",
"dataPath": "/system",
"schemaPath": "#/properties/system/oneOf",
"params": {
"passingSchemas": null
},
"message": "should match exactly one schema in oneOf",
"emUsed": true
}
]
},
"message": "should be a string or array of strings"
}
]
-------------------------------------------------------------
expect only one error in 'errors', but there are two for { packs: [{ system: [false] }] }:
[
{
"keyword": "type",
"dataPath": "/packs/0/system/0",
"schemaPath": "#/properties/packs/items/properties/system/oneOf/1/items/type",
"params": {
"type": "string"
},
"message": "should be string"
},
{
"keyword": "errorMessage",
"dataPath": "/packs/0/system",
"schemaPath": "#/properties/packs/items/properties/system/errorMessage",
"params": {
"errors": [
{
"keyword": "type",
"dataPath": "/packs/0/system",
"schemaPath": "#/properties/packs/items/properties/system/oneOf/0/type",
"params": {
"type": "string"
},
"message": "should be string",
"emUsed": true
},
{
"keyword": "oneOf",
"dataPath": "/packs/0/system",
"schemaPath": "#/properties/packs/items/properties/system/oneOf",
"params": {
"passingSchemas": null
},
"message": "should match exactly one schema in oneOf",
"emUsed": true
}
]
},
"message": "should be a string or array of strings"
}
]
According to the docs, 'for keywords "required" and "dependencies" it is possible to specify different messages for different properties'. However, when using ajv-errors with errorDataPath
set to property
, keyword messages are ignored.
The situation is exactly the same as in the test should replace required and dependencies errors with messages
, with the exception of the errorDataPath
being set for ajv in this case.
Is this an intended consequence of setting errorDataPath
to property
?
I would love to see support added for the $ref
keyword. I have several error messages that are used throughout my schemas, and it would be helpful to only have to define them once.
// error schema
{
"$id": "errors",
"string": "must be a string",
"basicObject": {
"type": { "$ref": "#/string" }
}
}
// schema
{
"type": "string",
"errorMessage": { "$ref": "errors#/basicObject" }
}
Reproduce
var Ajv = require('ajv');
var ajv = require('ajv-errors')(new Ajv({ useDefaults: true, allErrors: true, jsonPointers: true, verbose: true }), { singleError: true, keepErrors: false });
var schema = {
type: 'object',
properties: {
foo: {
oneOf: [
{ type: 'string' },
{ $ref: '#/definitions/bar' }
],
default: 'javascript',
errorMessage: 'should be string or object',
}
},
definitions: {
bar: {
type: 'object'
}
}
};
var validate = ajv.compile(schema);
validate({ foo: 42 }); // false
console.log(validate.errors); // processed errors
Expected output:
[
{
keyword: 'errorMessage',
dataPath: '/foo',
schemaPath: '#/properties/foo/errorMessage',
params: { errors: [Array] },
message: 'should be string or object',
schema: 'should be string or object',
parentSchema: {
oneOf: [Array],
default: 'javascript',
errorMessage: 'should be string or object'
},
data: 42
}
]
Actual output:
[
{
keyword: 'type',
dataPath: '/foo',
schemaPath: '#/definitions/bar/type',
params: { type: 'object' },
message: 'should be object',
schema: 'object',
parentSchema: { type: 'object' },
data: 42
},
{
keyword: 'errorMessage',
dataPath: '/foo',
schemaPath: '#/properties/foo/errorMessage',
params: { errors: [Array] },
message: 'should be string or object',
schema: 'should be string or object',
parentSchema: {
oneOf: [Array],
default: 'javascript',
errorMessage: 'should be string or object'
},
data: 42
}
]
Additional info
This has to do with the $ref
json pointer. If you place { type: 'object' }
directly in the oneOf
, it does work.
Hello, thanks for the library!
My schema looks like:
{
if: {
properties: {
fieldType: {
const: 'field1',
},
},
required: ['fieldType'],
},
then: {
$ref: '#/definitions/customDefinition',
required: ['field1'],
errorMessage: {
required: 'Required',
},
},
else: {
$ref: '#/definitions/customDefinition',
required: ['field2'],
errorMessage: {
required: 'Required',
},
},
definitions: {
customDefinition: {
type: 'object',
properties: { date: { format: 'date' } },
required: ['date'],
errorMessage: {
properties: { date: 'Custom error message' },
required: 'Required',
},
},
},
errorMessage: {
required: 'Required',
},
};
Now I need to copy-paste
errorMessage: {
required: 'Required',
},
in each subschema.
Is there an ability to set a global error message for required fields?
I know it's not right to open a issues here, but i can't find another way to reach the doT.js contributors, and I also know you are a very kind man, please check this PR olado/doT#269, I really need this fix, or can you add me as a doT.js contributor(and npm) ? I found the same issue was opened in 2015...
I'm really apologies for the issue and I will close it myself soon.
Hello and thanks a lot for this very helpful plugin!
I was wondering if there was a way to customize the way the error message is sent by using a label instead of the property name.
For example, by using this kind of syntax:
schema: {
query: {
type: 'object',
required: ['score'],
properties: {
score: {
type: 'integer',
label: 'スコア',
errorMessage: {
type: '${/score}が数字ではない'
}
}
}
}
I would get the following
スコア "true"が数字ではない
instead of
query/score "true"が数字ではない
I am sorry if it is already written somewhere. I have read so many articles today that my head might explodes by the end of the day.
Any plans to add more fine grained control? Like you mentioned here.
Example:
{
"type": "object",
"properties": {
"size": {
"type": "number",
"minimum": 4
}
},
"errorMessage": {
"properties": {
"size": {
"type": "Size must be a number",
"minimum": "Size cannot be less than 4"
}
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.