joi_1.default.validate不是一个函数。

36

在调用控制器逻辑之前,我想要验证我的Express路由。我使用joi创建了一个验证器,该验证器能够根据模式对象验证请求对象。

import { Request, Response, NextFunction } from 'express';
import joi, { SchemaLike, ValidationError, ValidationResult } from '@hapi/joi';
import { injectable } from 'inversify';

@injectable()
export abstract class RequestValidator {
    protected validateRequest = (validationSchema: SchemaLike, request: Request, response: Response, next: NextFunction): void => {
        const validationResult: ValidationResult<Request> = joi.validate(request, validationSchema, {
            abortEarly: false
        });

        const { error }: { error: ValidationError } = validationResult;

        if (error) {
            response.status(400).json({
                message: 'The request validation failed.',
                details: error.details
            });
        } else {
            next();
        }
    }
}

接下来,我创建了一个派生类,用于创建validationSchema并调用validateRequest方法。为了简单起见,我将展示“deleteUserById”验证。

import { Request, Response, NextFunction } from 'express';
import joi, { SchemaLike } from '@hapi/joi';
import { injectable } from 'inversify';

import { RequestValidator } from './RequestValidator';

@injectable()
export class UserRequestValidator extends RequestValidator {
    public deleteUserByIdValidation = async (request: Request, response: Response, next: NextFunction): Promise<void> => {
        const validationSchema: SchemaLike = joi.object().keys({
            params: joi.object().keys({
                id: joi.number().required(),
            })
        });

        this.validateRequest(validationSchema, request, response, next);
    }
}

重要提示: 我这样创建SchemaLike 是因为有些路由可能需要在一次运行中验证params、body、query

在调用路由时:

DELETE /users/1

验证总是失败。出现以下错误:

UnhandledPromiseRejectionWarning: TypeError: joi_1.default.validate不是一个函数

每次验证都会出现此错误,无论是否正确调用。有人知道如何解决吗?

17个回答

34

您可以通过更改以下内容来修复它:

joi.validate(request, validationSchema)

至:

validationSchema.validate(request)

joi.validate()在v16版本中不再受支持。这在API文档和发布说明中已经有了清晰的记录。


23

更新版本的joi无法与Joi.validate(req.body, schema);一起使用。不需要单独使用对象。请按以下方式使用。我成功地使用了它。如果我有任何错误,请让我知道:

更新后的joi版本不能与Joi.validate(req.body, schema);同时使用。不需要单独使用对象,可按以下方式使用。这种方法顺利地为我工作。如果我有任何问题,请告诉我:

const Joi = require('@hapi/joi');

const schema = Joi.object({
    name:Joi.string().min(3).required(),
    email:Joi.string().min(4).required().email(),
    password:Joi.string().min(6).required()
});





router.post('/register', async (req,res) => {


    //updated joi
    
   // This is a shorter version
    const { error } = schema.validate(req.body);

    // Error in response

    res.send(error.details[0].message);


    // WORKING WITH DEPRECATED VERSION
    // const Validation = Joi.validate(req.body,schema);
    // res.send(Validation);

15

我也遇到了joi.validate()不是一个函数的问题。我查看了他们的文档并找到了解决方案。

    const Joi = require('@hapi/joi');

const schema = Joi.object({
    name:Joi.string().min(6).required(),
    email:Joi.string().min(6).required().email(),
    password:Joi.string().min(6).required()
});

router.post('/register',  (req, res) => {

    // VALIDATE BEFORE SAVING A USER 
    const Validation = schema.validate(req.body);
    res.send(Validation);

    
})

这个按预期工作,并且没有出现其他错误。


13

在使用express-joi-validation时遇到了同样的问题。

如果您可以使用版本15,则降级Joi将解决问题。

npm uninstall --save @hapi/joi
npm install --save @hapi/joi@15.0.3

7
抱歉,我会拒绝投票因为这已经不再实际。v15已经被弃用了,API也有所变化。请参考Eran Hammer的答案,他是正确的。 - Sergey Yarotskiy
1
降低它的评分。你不应该使用已弃用的API。 - Linus Fernandes

7
你可以通过将 Joi.validate(request, validationSchema) 更改为 validationSchema.validate(request) 来解决此问题,因为在 v16 中不再支持 Joi.validate()
对于新版本:
const schema = Joi.object({ name: Joi.string() .min(6) .required(),
email: Joi.string() .min(6) .required() .email(),
password: Joi.string() .min(6) .required() });

const validation = schema.validate(req.body);

5
代替降级Joi版本,最好快速查看最新版本的API,并检查正确使用它的方法。
这是目前最新的Joi API(16.1.7)链接在此处,您可以查看使用validate的示例。
另外,为了确保您知道您使用的库的下一个版本发生了什么变化,建议查看发布说明。这里是Joi 16版发布说明的链接在此处,您可以查看所有更改/新功能,以及关于validate方法的信息:

删除Joi.validate()和Joi.describe()(直接在模式上调用)(#1941)


1
这个答案可行。在模式中,放置const schemaName= Joi.object({,然后是您的常规模式数据:请注意需要Joi.object。调用它时,只需使用schemaName.validate(req.body) [而不是旧版本的Joi.validate(req.body, schemaName)]。 - Nhon Ha

3

针对新版本:

const schema = Joi.object({ name: Joi.string() .min(6) .required(),
email: Joi.string() .min(6) .required() .email(),
password: Joi.string() .min(6) .required() });

const validation = schema.validate(req.body);
res.send(validation);

1
Following works with the latest version ("@hapi/joi": "^17.1.1"):

    const Joi = require("@hapi/joi");

    const schema = Joi.object({
      name: Joi.string().min(6).required(),
      email: Joi.string().min(6).required().email(),
      password: Joi.string().min(6).required(),
    });
    
  router.post("/register", async (req, res) => {
  const { error } = schema.validate(req.body);

  if (error) {
    res.json({ ErrorMessage: error.details[0].message });
  } else {
    res.json({ message: "valid data" });
  }

});

1

npm i joi

joi v17.4.x 资源:https://joi.dev/api/?v=17.4.2

const schema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().required().min(5),
});

 const result = schema.validate(YourRequest.body);

你的格式让我感到困惑,以至于我无法确定这是仅仅是代码还是一个“测试”随机字符的帖子。我们假设这是仅仅是代码。 - Yunnosch
虽然此代码可以解决问题,但包括解释这样做的原因和方法将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加说明并指示适用的限制和假设。 - Yunnosch
1
链接的内容不被视为答案的一部分,因此仍然只是代码。而且,读起来难以理解或格式混乱。请写一些有解释性的文字,并尝试更加正式化的格式。 - Yunnosch
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

1

你可以检查你的文件中是否安装并需要了 @hapi/joi 模块。

对于验证,可以采用以下方法。

const schema= Joi.object().keys({

    name: Joi.string().min(6).required(),
    email: Joi.string().min(6).email(),
    password: Joi.string().min(6).required()
});

 const validation = schema.validate(req.body);
    if(validation.error){
        res.status(400).send(validation.error.details[0].message);
        return ;
    }

我认为这会起作用


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接