Проверка Joi - как требовать или необязательное поле на основе другого ключа существует в массиве? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть эта схема Джой:

  let schema = {};

  let stations = {
    contact: {
      first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
    },
    address: {
      place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').required().error(JoiCustomErrors),
      city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
      street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
      house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
    },
    passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
    notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
  };
  schema.stations = Joi.array().items(stations).min(1).max(5).required().error(JoiCustomErrors);

Как видите, schema.stations - это массив из минимум 1 и максимум 5 элементов. Я хочу, чтобы у каждого из элементов было поле «address.place», только если существует "contact.first_name" AND "contact.last_name" AND "contact.phone" (или заполнено должным образом на основе схемы).

Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Вы можете использовать Joi.when() и создать схему, подобную этой:

Joi.object().keys({
    contact: Joi.object().keys({
        first_name: Joi.string(),
        last_name: Joi.string(),
        phone: Joi.string(),
    }),
    address: Joi.object().keys({
        place: Joi.string(),
        city: Joi.string().min(2).max(30),
        street: Joi.string(),
        house_number: Joi.string()
    }).when('contact', {
        is: Joi.object().keys({
            first_name: Joi.exist(),
            last_name: Joi.exist(),
            phone: Joi.exist(),
        }),
        then: Joi.object({ place: Joi.required() }).required(),
        otherwise: Joi.object({ place: Joi.forbidden() })
    }),
    passengers_amount: Joi.number(),
    notes: Joi.string()
});

Я просто упростил вашу шему, чтобы ее было легко понять.

По сути, мы говорим здесь, если concat.first_name , concat.last_name и concat.phone существует , тогда address и address.place являются обязательными , в противном случае address.place является запрещено .

Например, этот объект потерпит неудачу , поскольку адрес не существует:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    }
}

и это не удастся, потому что address.place не существует:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    },
    concact: {
    }
}

Наконец, в соответствии с определенной схемой, этот объект пройдет:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    },
    concact: {
        place: 'd'
    }
};
0 голосов
/ 07 июня 2019

Благодаря Soltex это правильная схема, которую следует использовать (но, пожалуйста, обратитесь к внесенным мною изменениям):

Joi.object().keys({
    contact: {
      first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
    },
    address: Joi.object().keys({
      place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').error(JoiCustomErrors),
      city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
      street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
      house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
    }).when('contact', {
      is: Joi.object().keys({
        first_name: Joi.string().min(1),
        last_name: Joi.string().min(1),
        phone: Joi.string().min(1),
      }),
      then: Joi.object({ place: Joi.required() }).required(),
      otherwise: Joi.object({
        place: Joi.optional().allow("")
      })
    }),
    passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
    notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
  })

Обратите внимание, что меняется от моего ответа к ответу Soltex: он сделал когда "contact.first_name" "contact.last_name" "contact.phone" было: Joi.exists () . Это нехорошо, поскольку таким образом даже пустой объект «существует», а затем требует от пользователя предоставить «address.place». Мы не хотим такой вещи, нам нужно по одному символу в каждом из этих полей.

Кроме того, в ответах Soltex в противном случае используется Joi.forbidden () , хотя здесь это нежелательное поведение - нам все еще нужно разрешить пользователю предоставлять место, даже без контакта , но это не должно быть обязательным, поэтому вместо этого я использовал: Joi.optional () .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...