使用Joi校验接口参数报错joi.validate is not a function如何解决
问题原因
joi.validate is not a function 报错是因为你使用的是 Joi v16及以上版本,这个版本开始官方移除了全局静态方法Joi.validate(),你后续尝试的Joi.schema(ctx.request.body)属于错误写法,Joi本身不存在schema这个全局方法。
正确修复方案
Joi新版本的校验逻辑调整为:先定义校验规则schema实例,再调用schema实例上的validate方法传入待校验数据,对应你代码里的校验部分修正如下:
exports.localLogin = async (ctx) => { // 定义校验规则,新版本Joi.object()可直接传入规则对象,无需链式调用keys() const schema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().required() }); // 调用schema实例的validate方法做校验,而非全局Joi.validate const { error, value: validParams } = schema.validate(ctx.request.body, { abortEarly: false, // 可选,设为false会返回所有参数的校验错误,默认碰到第一个错误就终止 allowUnknown: false // 可选,设为true允许请求体携带未定义的字段,默认false }); if(error) { ctx.status = 400; // Bad Request // 可选:把具体校验错误信息返回给前端 ctx.body = { msg: error.details.map(item => item.message).join('; ') }; return; } // 校验通过后,优先使用校验返回的validParams,避免直接使用原始请求体带来的多余字段/类型异常问题 const { email, password } = validParams; let account = null; try { account = await Account.findByEmail(email); } catch (e) { ctx.throw(500, e); } if(!account || !account.validatePassword(password)) { ctx.status = 403; // Forbidden return; } ctx.body = account.profile; };
额外注意点
- 如果你确实需要使用老的
Joi.validate()写法,需要把本地安装的Joi降级到v15及以下版本,执行npm i joi@15即可,但更推荐使用新版本API。 - 不要照搬发布时间过早的Joi教程,v16之后属于大版本迭代,核心校验API的调用方式变化很大,老教程的写法在新版本里基本都无法运行。
内容的提问来源于stack exchange,提问作者JIHYEON
相关产品推荐
相关产品推荐

