如何针对架构中的不同键运行自定义验证?

Mat*_*ews 2 validation node.js joi

我正在使用 Joi 来验证用户提交的表单数据。数据包含银行详细信息:此处的相关信息是accountNumbersortCode。我需要获取两个输入的值并通过外部 API 运行它们以确认它们一起有效。

我正在努力编写一个自定义的 Joi 扩展,它可以获取数据中另一个字段的值。这是我尝试过的简化版本:

const baseJoi = require('joi');

const bankDetails = joi => {
    return {
        name: 'bankDetails',
        base: joi.number().required(),
        rules: [
            {
                name: 'accountNumber',
                params: {
                    number: joi.number().required()
                },
                validate(params, value, state, options) {
                    console.log(value); // returns 12-34-46 (sortCode)
                    console.log(params.number); // returns a [Function: ref] object
                    console.log(state.parent.accountNumber); // returns 88888888, but feels "wrong"
                }
            }
        ]
    };
};

const Joi = baseJoi.extend([bankDetails]);

const validateBankDetails = () => {
    return Joi.bankDetails().accountNumber(Joi.ref('accountNumber')).required();
};

const schema = Joi.object({
    accountNumber: Joi.number().required(),
    sortCode: validateBankDetails(),
});
Run Code Online (Sandbox Code Playgroud)

我知道我可以Joi.ref()在 Joi 自己的验证器中使用(例如类似Joi.number().less(Joi.ref('max'))),但在这里我需要获取该键 ( )的accountNumber并将其传递给另一个函数(连同sortCode值)。是否有 Joi 批准的方法?我可以从state参数中获得我想要的值,但这感觉有点反模式。

Mar*_*lvy 6

您是否尝试过在普通的旧 Joi 对象上使用custom 方法而不是扩展?我认为它可能会以更直接的方式为您提供您想要的东西:

const schema = Joi.object({
  accountNumber: Joi.number().required(),
  sortCode: Joi.number().required(),
})
  .custom((obj, helpers) => {
    // you have access to the full object above.
    const { accountNumber, sortCode } = obj;

    // Do your validation
    const isValid = doSomething(accountNumber, sortCode);

    if (!isValid) {
      throw new Error('Invalid input');
    }

    // Just pass the object on through if things work.
    return obj;
  });
Run Code Online (Sandbox Code Playgroud)

  • 但是,这不会注册特定属性的错误。 (5认同)