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

NestJS+GraphQL自定义校验错误响应格式方案咨询

NestJS GraphQL 自定义校验错误格式(class-validator风格)

问题背景

使用NestJS + GraphQL + PostgreSQL时,校验失败返回的错误格式不符合需求,需要统一改为class-validator风格的响应,要求包含数组形式的message、BAD_USER_INPUT错误码、400状态码等。

解决方案

1. 完善DTO校验规则

修正DTO中的校验配置,确保class-validator规则正确生效,同时匹配GraphQL字段定义:

import { Field, InputType } from "@nestjs/graphql";
import { IsEnum, MinLength, IsOptional, IsNumber } from "class-validator";
import { PoolType, Status } from "src/pool/entities/pool.enum";

@InputType()
export class CreatePoolInput {
  @Field()
  @IsNumber()
  orgId: number;

  @Field({ nullable: true }) // 可选字段需显式声明nullable
  @IsOptional()
  @MinLength(3) // 添加长度校验规则
  clientId?: string; // 根据校验需求调整类型,这里假设为字符串

  @IsEnum(PoolType)
  @Field()
  type: PoolType;

  @Field({ nullable: true })
  name: string;

  @Field({ nullable: true })
  description: string;

  @Field({ nullable: true })
  list: string;

  @IsEnum(Status)
  @Field()
  status: Status;
}

2. 全局配置ValidationPipe

在AppModule中开启全局校验管道,确保class-validator的错误被正确抛出:

import { Module } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';

@Module({
  providers: [
    {
      provide: APP_PIPE,
      useValue: new ValidationPipe({
        transform: true, // 自动转换请求数据类型
        whitelist: true, // 过滤DTO未定义字段
        forbidNonWhitelisted: true, // 非白名单字段直接报错
        errorHttpStatusCode: 400, // 校验失败返回400状态码
      }),
    },
  ],
})
export class AppModule {}

3. 修改formatError函数统一错误格式

更新GraphQL的formatError函数,分别处理GraphQL内置校验错误和class-validator校验错误,统一转换为期望格式:

formatError: (error) => {
  // 处理GraphQL内置校验错误(如必填字段缺失、类型不匹配)
  if (error.extensions?.code === 'GRAPHQL_VALIDATION_FAILED') {
    const fieldMatch = error.message.match(/Field \"(\w+\.\w+)\"/);
    const fieldName = fieldMatch ? fieldMatch[1].split('.')[1] : 'unknown field';
    
    let errorMessage: string;
    if (error.message.includes('was not provided')) {
      errorMessage = `${fieldName} is required`;
    } else if (error.message.includes('type mismatch')) {
      errorMessage = `${fieldName} has invalid type`;
    } else {
      errorMessage = error.message;
    }

    return {
      message: [errorMessage],
      code: 'BAD_USER_INPUT',
      name: 'UserInputError',
      statusCode: 400,
    };
  }

  // 处理class-validator抛出的校验错误
  if (error.extensions?.response?.statusCode === 400) {
    return {
      message: Array.isArray(error.extensions.response.message) 
        ? error.extensions.response.message 
        : [error.extensions.response.message],
      code: 'BAD_USER_INPUT',
      name: 'UserInputError',
      statusCode: 400,
    };
  }

  // 其他服务器错误保持原有格式
  return {
    message: [error.message],
    code: error.extensions?.code || 'SERVER_ERROR',
    name: error.extensions?.name || error.name,
    statusCode: error?.extensions?.response?.statusCode || error?.statusCode || 500,
  };
},

效果验证

修改后,校验失败时会返回符合要求的响应格式:

{
  "errors": [
    {
      "message": [
        "clientId must be longer than or equal to 3 characters"
      ],
      "code": "BAD_USER_INPUT",
      "name": "UserInputError",
      "statusCode": 400
    }
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:27:24