You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Joi验证输出警告而非抛出错误?

问题描述

使用Joi包做参数验证时,当传入无效值(比如用数字替代字符串),当前的验证逻辑会抛出错误,阻止事件存入数据库。现在需要调整为仅记录验证错误的警告日志,不中断流程,允许事件正常存入数据库。

当前相关代码如下:

注册命令的Joi Schema

const registerCommandSchema = baseEntitySchema.append({
  name: Joi.string().required(),
  type: Joi.string()
    .valid(...Object.values(EntityType))
    .required(),
  manualEntry: Joi.boolean().required(),
  sourceIp: Joi.string().ip().required(),
  caid: Joi.string(),
  status: Joi.string().valid(...Object.values(Status)),
  shortId: Joi.string(),
});

export class RegisterCommand extends ICommand<RegisterCommandDto> {
  schema(): Joi.ObjectSchema {
    return registerCommandSchema;
  }
}

基础命令抽象类(ICommand)

export abstract class ICommand<Dto> {
  constructor(public readonly dto: Dto) {
  }

  /**
   * Returns the sub-class specific Joi.ObjectSchema to be used during this.validate()
   */
  abstract schema(): Joi.ObjectSchema;

  /**
   * Validate command to ensure there is no invalid field values
   * e.g. missing properties, invalid values ... etc
   * Any validation issue => throws an Error.
   */
  validate(): void {
    const { error } = this.schema().validate(this.dto);
    if (!error) {
      return;
    }
    throw new ClientError(error.details[0].message);
  }
}

命令处理器

import { IHookAction, HookAction } from '@nestpack/hooks';
import { RegisterCommand } from '../impl';
import { EntityRepository } from '../../repositories/entityRepository';

@HookAction(RegisterCommand)
export class RegisterCommandHandler implements IHookAction {
  constructor(private readonly repository: EntityRepository) {}

  async handle(command: RegisterCommand) {
    console.log('RegisterCommandHandler.execute');
    console.log(JSON.stringify(command, null, 2));

    command.validate();

    const { dto } = command;
    await this.repository.register(dto);
  }
}
解决方案

核心是修改ICommand中的validate方法,移除抛出错误的逻辑,替换为日志记录;同时确保处理器流程不会被中断。

步骤1:修改ICommand的validate方法

将原来抛出ClientError的逻辑,替换为记录警告日志。如果项目中有统一的日志工具(比如你提到的info/warn方法),确保正确引入并使用;如果没有,用console.warn临时替代:

export abstract class ICommand<Dto> {
  constructor(public readonly dto: Dto) {
  }

  abstract schema(): Joi.ObjectSchema;

  validate(): void {
    const { error } = this.schema().validate(this.dto);
    if (!error) {
      return;
    }
    // 替换为项目实际的日志工具,比如logger.warn
    console.warn(`验证警告:${error.details.map(d => d.message).join('; ')}`);
    // 如果你的info方法是日志工具的实例方法,确保已注入或正确引用
    // 例如:this.logger.warn(error.details[0].message);
  }
}

注意:如果之前替换throw为info没生效,检查以下几点:

  • info方法是否正确引入(比如是否是日志服务的实例,有没有在类中注入)
  • 日志级别是否配置正确(比如info级别的日志是否被输出到控制台/文件)
  • 错误信息是否被正确获取(比如error.details是否为空,或者需要遍历所有错误)

步骤2:确保处理器流程正常执行

修改后的validate方法不再抛出错误,因此处理器中的command.validate()执行后,会直接继续执行后续的repository.register(dto)逻辑,无需额外修改处理器代码。

验证效果

当传入无效负载时,控制台/日志系统会输出验证错误的警告信息,同时事件会正常存入数据库,不会被中断。

内容的提问来源于stack exchange,提问作者Nickie Ferrante

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:18:20