How to set up a custom AJV keyword?
Asked Answered
J

1

6

I'm using ajv and want to add a custom validator inspecting a given object. This custom validator should either return true or fail with the correct error message. Based on

I started with the following sample code

const Ajv = require("ajv");
const ajv = new Ajv({ allErrors: true });

ajv.addKeyword({
  keyword: "eachPropIsTrue",
  type: "object",
  schemaType: "boolean",
  code(context) {
    const { data } = context;
    const eachPropIsTrue = Object.values(data).every(value => !!value);

    context.fail(!eachPropIsTrue);
  },
})

const schema = {
  type: "object",
  eachPropIsTrue: true,
  properties: {
    a: { type: "boolean" }
  },
  required: [ "a" ],
  additionalProperties: false
};

const validate = ajv.compile(schema);
console.log(validate({ a: true })); // true
console.log(validate({ a: false })); // true but should be false!
console.log(validate({ })); // false

Unfortunately I'm facing two problems:

  • The second validation does not fail although I would expect it to fail
  • Where do I have to pass in information about the constructed error message?

When inspecting the data variable inside the code function I can see that it does not contain the current object. So what is the correct way to set up a custom keyword?

I'm looking for a sample function like

validate(theObject): boolean | string => {
  const anyPropIsFalse = Object.values(data).some(value => value === false);

  if(anyPropIsFalse) {
    return 'Any prop is false!';
  }

  return true;
};

or maybe a function returning void but using context.fail('Any prop is false!');


Sidenote:

My real world usecase scenario is an object with two properties where one is an object with an id and the other property is an array holding objects with ids. I have to make sure that all ids from both properties are completely unique.

Julio answered 30/3, 2022 at 7:52 Comment(0)
V
4

This makes the example to work as intended.

ajv.addKeyword({
  keyword:    "eachPropIsTrue",
  type:       "object",
  schemaType: "boolean",
  compile:    () => data => Object.values(data).every(value => !!value)
});

Anyway I strongly suggest to better check ajv user-defined keywords documentation.

Voltammeter answered 1/4, 2022 at 15:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.