如何在 JOI 17 中添加自定义验证器?

Dav*_*ein 1 javascript joi

我正在使用 JOI 14,似乎找不到升级到 17 的指南。我看到人们发布了有关 JOI 16 的类似问题,但最后一次更新是在 3 个月前。type根据我在如何在 Joi 中添加自定义验证器函数? 中看到的内容,它看起来不像16 中所要求的那样。。

我正在查看https://joi.dev/api/?v=17.3.0#extensions,其描述typeThe type of schema. Can be a string, or a regular expression that matches multiple types.

我尝试过这样的事情:

    const snakeAlpha = joi => {
      return {
        type: 'object',
        name: 'snakeAlpha',
        base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
      };
    };
    
    const customJoi = Joi.extend({
      type: 'object',
      rules: {
        snakeAlpha
      }
    });
Run Code Online (Sandbox Code Playgroud)

它给了我这个错误:

    ValidationError: {
      "type": "object",
      "rules": {
        "snakeAlpha" [1]: "[joi => {\n  return {\n    type: 'object',\n    name: 'snakeAlpha',\n    base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)\n  };\n}]"
      }
    }
    
    [1] "rules.snakeAlpha" must be of type object
Run Code Online (Sandbox Code Playgroud)

既然这么说我就很困惑了object。我也尝试过string,因为这就是基础,但它有相同的错误消息。

更新 我还意识到原来的示例只涵盖了一个不引用 joi (正则表达式)的简单规则。我还有引用其他自定义验证器的验证器,如下所示。解决此案也可以获得奖励积分。

const arrayKebabAlpha = joi => {
  return {
    type: 'string',
    name: 'arrayKebabAlpha',
    base: joi.array().items(joi.kebabAlpha())
  };
};
Run Code Online (Sandbox Code Playgroud)

Ank*_*nkh 5

对于如此有用的功能,Joi 扩展的文档令人失望地乏善可陈。幸运的是,Joi 的很多核心都是使用扩展编写的,因此可以通过查看源代码学到很多东西。

如果我将你的规则写为扩展,它会是这样的:

const customJoi = Joi.extend(joi => ({
    type: 'string',
    base: joi.string(),
    messages: {
        'string.snakeAlpha': '{{#label}} must be snake case'
    },
    rules: {
        snakeAlpha: {
            validate(value, helpers)
            {
                if (!/^[a-z]+(_[a-z]+)*$/.test(value))
                {
                    return helpers.error('string.snakeAlpha', { value });
                }

                return value;
            }
        }
    }
}));
Run Code Online (Sandbox Code Playgroud)

可以这样使用:

customJoi.object().keys({
    foo: customJoi.string().snakeAlpha()
});
Run Code Online (Sandbox Code Playgroud)

更新

我不确定这是否是处理依赖扩展的正确方法,但这就是我通常处理它们的方式......

我首先在数组中定义扩展,确保首先定义依赖扩展。然后,我将重复使用前一个实例来迭代数组customJoi,以便下一个扩展包含之前定义的扩展。一个简单的工作示例可能会比我用语言更好地解释!

(我还简化了扩展,使其更符合您习惯使用它们的方式)

const Joi = require('joi');

let customJoi = Joi;

const extensions = [
    joi => ({
        type: 'snakeAlpha',
        base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
    }),
    // this instance of 'joi' will include 'snakeAlpha'
    joi => ({
        type: 'kebabAlpha',
        base: joi.string().regex(/^[a-z]+(-[a-z]+)*$/)
    }),
    // this instance of 'joi' will include 'snakeAlpha' and 'kebabAlpha'
    joi => ({
        type: 'arrayKebabAlpha',
        base: joi.array().items(joi.kebabAlpha())
    })
];

extensions.forEach(extension =>
    customJoi = customJoi.extend(extension));

customJoi.assert([ 'hello-world' ], customJoi.arrayKebabAlpha());
Run Code Online (Sandbox Code Playgroud)