Условная схема валидатора Joi

Мне нужно создать динамическую схему для проверки моего запроса api-запроса в node js с помощью валидатора Joi в зависимости от ключа в запросе запроса. . Скажем, приведенный ниже шаблон является моими действительными запросами.

Я использую hapi/joi версию 16.1.8

Комбинация 1

{ type: 1, firstname: 'user first name', lastname: 'user last name'}

Комбинация 2

{ type: 2 , salary: 1000, pension: 200}

Комбинация 3

{ type: 3 , credit: 550, debit: 100}

Как видите, ключи объекта различаются в зависимости от значения type. Как с этим справиться правильно?

Мы можем обработать два условия, используя Joi.alternatives, например

const schema = Joi.alternatives().conditional(Joi.object({ type: 1 }).unknown(), {
    then: Joi.object({
        type: Joi.string(),
        firstname: Joi.string(),
        lastname: Joi.string()
    }),
    otherwise: Joi.object({
        type: Joi.number(),
        salary: Joi.any(),
        pension: Joi.any()
    })
});

Но как это сделать для 3 условий?


person Nitheesh    schedule 22.01.2020    source источник
comment
Я бы написал промежуточное ПО предварительного маршрута, которое будет условно определять, какую схему использовать. Но на Ваш вопрос лучше всего подходит ответ Грегори НЕЙТ.   -  person num8er    schedule 22.01.2020
comment
@ num8er Я пробовал решение из документации, оно тоже было правильным. Но когда я попытался добавить то же самое, у меня возникла ошибка. В качестве ответа я добавил еще один рабочий пример.   -  person Nitheesh    schedule 23.01.2020


Ответы (5)


Я добился того же немного другим способом. Публикуйте то же самое здесь, так как это может быть полезно для кого-то в будущем.

const schema = Joi.object({
    type: Joi.number().required().valid(1, 2, 3),
    firstname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
    lastname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
    salary: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
    pension: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
    credit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
    debit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
}))

Это сработало отлично, как и ожидалось.

Когда значение типа 1, объект должен иметь только type, firstname и lastname

Когда значение типа 2, объект должен иметь только type, salary и pension

Когда значение типа 3, объект должен иметь только type, credit и debit

Любая другая комбинация будет выдана как ошибка промежуточного слоя валидатора joi. Также любое другое значение типа, кроме 1, 2 и 3, будет выдавать ошибку.

person Nitheesh    schedule 23.01.2020

Меня устраивает!

var Joi = require('joi');

var schema = {
    a: Joi.any().when('b', { is: 5, then: Joi.required(), otherwise: Joi.optional() }),
    b: Joi.any()
};

var thing = {
    b: 5
};
var validate = Joi.validate(thing, schema);

// returns
{
    error: null,
    value: {
        b: 5
    }
}

Это ссылка.

person soamazing    schedule 06.07.2020

В документации похоже, что switch действителен ключ для использования вместе с alternatives.conditional. Не могли бы вы попробовать следующее?

const schema = Joi.alternatives().conditional(Joi.object({
  type: 1
}).unknown(), {
  switch: [{
    is: 1,

    then: Joi.object({
      type: Joi.string(),
      firstname: Joi.string(),
      lastname: Joi.string(),
    }),
  }, {
    is: 2,

    then: Joi.object({
      type: Joi.number(),
      salary: Joi.any(),
      pension: Joi.any(),
    }),
  }, {
    // ...
  }],
});

ИЗМЕНИТЬ:

Не удалось найти нигде примера использования ключевого слова switch ...

Но нашел другой способ добиться этого в hapijs / joi github

const schema = Joi.object({
     a: Joi.number().required(),
     b: Joi.alternatives()
             .conditional('a', [
                 { is: 0, then: Joi.valid(1) },
                 { is: 1, then: Joi.valid(2) },
                 { is: 2, then: Joi.valid(3), otherwise: Joi.valid(4) }
    ])
});
person Orelsanpls    schedule 22.01.2020
comment
Это выдает мне ошибку Error: "switch" can not be used with a schema condition. Я использую hapi/joi версию 16.1.8. - person Nitheesh; 23.01.2020
comment
@Nitheesh в 16.1.8 также упоминается ключевое слово switch . Это означает, что мы используем его неправильно, позвольте мне взглянуть на какой-нибудь пример, который я смог найти - person Orelsanpls; 23.01.2020
comment
ваш второй синтаксис правильный. Ответ, который я опубликовал, также является реализацией того же самого в моем случае. Спасибо :) - person Nitheesh; 23.01.2020

Я пытался найти способ сделать что-то подобное. Тогда я смог разобраться.

const Joi = require('joi');
const schema = Joi.object({
  type: Joi.number().valid(1,2,3),
  // anything common
}).when(Joi.object({type: Joi.number().valid(1)}).unknown(), {
  then: Joi.object({
    firstname: Joi.string(),
    lastname: Joi.string(),
  })
})
.when(Joi.object({type: Joi.number().valid(2)}).unknown(), {
  then: Joi.object({
    salary: Joi.number(),
    pension: Joi.number(),
  })
})
.when(Joi.object({type: Joi.number().valid(3)}).unknown(), {
  then: Joi.object({
    credit: Joi.number(),
    debit: Joi.number(),
  })
});

person orangedietc    schedule 17.02.2021

Я хотел сделать то же самое, но вместо параметра запроса условие должно зависеть от метода запроса. Я пришел к следующему решению:

const schema = Joi.when(Joi.ref("$requestMethod"), {
  switch: [
    {
      is: "POST",
      then: Joi.object({
        name: Joi.string().trim().max(150).required(),
        description: Joi.string().max(255),
        active: Joi.boolean().required(),
        }),
      }),
    },
    {
      is: "PUT",
      then: Joi.object({
        name: Joi.string().trim().max(150).required(),
        description: Joi.string().max(255),            
      }),
    },
  ],
});


schema.validate(req.body, { context: { requestMethod: req.method } });

Документация по условию Joi when () https://joi.dev/api/?v=17.4.1#anywhencondition-options

person Alex    schedule 22.07.2021