AJV - Проверка свойства является функцией

Я использую AJV для проверки объекта «настройки». Я хочу добавить новое свойство onFeedbackChange, которое может быть функцией (не обязательно).

  const ajv = new Ajv({
    allErrors: true,
  });
  ajv.addKeyword('function', {
    valid: true,
    validate: function (data) {
      return typeof data === 'function';
    }
  });
  const validate = ajv.compile(settingsSchema);

Схема:

  feedback:
    type: object
    properties:
      enabled:
        type: boolean
      saveFeedback: *endpoint
      updateFeedback: *endpoint
      onFeedbackChange: function
    additionalProperties: false
    required:
    - enabled
    - saveFeedback
    - updateFeedback

Но это не удается с:

Ошибка: недопустимая схема: data.properties['modules'].properties['feedback'].properties['onFeedbackChange'] должен быть объектом, логическим

Интересно, как выполнить проверку и почему это не встроено.


ajv
person Vadorequest    schedule 12.02.2020    source источник


Ответы (1)


Мы используем это для проверки данных, содержащих компонент React:

Данные, которые мы проверяем:

const config = {
    id: 'dailyGraph',
    component: BarGraph, // <-- react component (function)
    type: 'bar',
    ...
}

Наша схема:

const barSchema = {
    $schema: 'http://json-schema.org/draft-07/schema',
    $id: 'dailyGraph',
    type: 'object',
    readOnly: true,
    title: 'Schema for validating graph config',
    properties: {
        id: { 
            $id: '#/properties/id',
            type: 'string'
        },
        component: {
            $id: '#/properties/component',
            instanceof: 'Function', // <-- ajv custom keyword
        },
        type: {
            $id: '#/properties/type',
            type: 'string',
            enum: ['bar','pie'],
        }
        ...
    },
    required: ['id', 'assays', 'graphType']
};

И синтаксис .addKeyword как здесь: https://github.com/epoberezkin/ajv/issues/147#issuecomment-199371370

const ajv = new Ajv();
const { id } = config;
const CLASSES = { Function: Function, ... };

ajv.addKeyword('instanceof', {
  compile: schema => data => data instanceof CLASSES[schema]
});

ajv.validate(barSchema, config)
  ? res(true)
  : console.error(`Graph config error for ${id}: ${ajv.errorsText()}`);

Передача component в виде строки (или чего угодно, кроме функции) выдает: Graph config error for dailyGraph: data.component should pass "instanceof" keyword validation

person DavidP    schedule 03.05.2020
comment
Я еще не проверял это, но выглядит красиво и очень похоже на то, что я хотел сделать тогда! :) - person Vadorequest; 04.05.2020
comment
Надеюсь, это помогло. Что изначально бросило меня в цикл, так это то, что schema внутри цикла .addKeyword не должен называться в соответствии с вашей схемой проверки. Как только я разобрался с примером в указанном тикете - все заработало. - person DavidP; 04.05.2020
comment
Это также будет работать в ajv v8 const classes = {Function: Function}; ajv.addKeyword({keyword: 'instanceof', schemaType: 'string', validate (schema, data) { return data instanceof classes[schema] }}) - person Marc Bachmann; 17.05.2021