【问题标题】:Joi validation for a decimal number not working properly十进制数的 Joi 验证无法正常工作
【发布时间】:2021-10-29 18:19:13
【问题描述】:

我正在验证我正在处理的 API 之一的请求正文,以便在数据库中插入数据。 DB 的精度为 3。

下面是架构 -

const insertDetails = {
  body: Joi.object({
    id: Joi.string().length(6).required(),
    startdate: Joi.date().format('YYYY-MM-DD').required(),
    enddate: Joi.date().format('YYYY-MM-DD').required(),
    role: Joi.number().valid(5).required(),
    fnum: Joi.number().less(1.500).precision(3).required(),
    user: Joi.string().max(8).required()
  })
}

我的理解是对于 fnum,它只允许小数精度高达 3,如果有像 1.345678 这样的数字表示精度应该是 3,则应该抛出错误。

但是在插入数据时,它会在数据库中四舍五入到小数点后 3 位。

我尝试在线搜索,发现我们可以验证或将转换设置为 false,但我很难仅针对此处的一个字段,即 fnum

Joi.validate(insertDetails, {"convert": false})

我在上面添加了一行,但它抛出了一个错误提示

TypeError: Joi.validate is not a function

关于如何验证请求中 fnum 的精度以及如果精度更高应该抛出错误的任何建议?

【问题讨论】:

    标签: javascript node.js validation joi


    【解决方案1】:

    像这样定义架构-

    const insertSchema = Joi.object({
        id: Joi.string().length(6).required(),
        startdate: Joi.date().format('YYYY-MM-DD').required(),
        enddate: Joi.date().format('YYYY-MM-DD').required(),
        role: Joi.number().valid(5).required(),
        fnum: Joi.number().less(1.500).precision(3).required(),
        user: Joi.string().max(8).required()
      })
    

    然后将验证功能与架构一起使用-

    const {error, value} = insertSchema.validate(req.body,{"convert": false});
    

    您可以将req.body 对象作为第一个参数,下一个参数将是选项。

    这个函数会返回一个带有errorvalue的对象。


    或者你可以为路由创建一个这样的中间件-

    const validateRequest = (
      req,
      next,
      schema,
      options = {
        abortEarly: false, // include all errors
        allowUnknown: true, // ignore unknown props
        stripUnknown: true, // remove unknown props
      },
    ) => {
      const { error, value } = schema.validate(req.body, options);
      if (error) {
        const error_ = new Error(`Validation error: ${error.details.map((x) => x.message).join(', ')}`);
        error_.statusCode = 400;
        throw error_;
      } else {
        req.body = value;
        next();
      }
    };
    

    然后使用validateRequest 函数创建您的架构-

    
    const insertSchema = (req, res, next) => {
      const schema = Joi.object({
          id: Joi.string().length(6).required(),
          startdate: Joi.date().format('YYYY-MM-DD').required(),
          enddate: Joi.date().format('YYYY-MM-DD').required(),
          role: Joi.number().valid(5).required(),
          fnum: Joi.number().less(1.5).precision(3).required(),
          user: Joi.string().max(8).required(),
        });
      validateRequest(req, next, schema);
    };
    

    然后在你的路由器中使用它作为中间件-

    router.post('/create-post', insertSchema, (req, res, next) => {
       // Do rest of the code
    });
    

    【讨论】:

    • 非常感谢萨希德。我相信中间件选项是我想要做的。基本上在选项字段中,我必须添加 convert : false 对吗?当我调用 validateRequest 时,它应该是这样的 - validateRequest(req, next, insertSchema) ?
    • 抱歉,我错过了 insertSchema funs 中的模式变量。刚刚更新我的答案,请看一下!
    • 是的,您必须在validateRequest func 中将convert : false 作为选项传递。
    • 出现错误 - ``` _original: [Function: insertSchema], details: [ { message: '"value" must be of type object', path: [], type: 'object.基',上下文:{类型:'对象',标签:'值',值:[函数:insertSchema]}}]}```
    • 这里不同的是我在 router.post 中使用express-validation 的验证方法。所以它类似于 API 调用中的 validate(insertSchema)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多