在 nest.js 控制器中使用类验证器验证嵌套对象
Posted
技术标签:
【中文标题】在 nest.js 控制器中使用类验证器验证嵌套对象【英文标题】:validate nested objects using class-validator in nest.js controller 【发布时间】:2019-05-08 02:21:41 【问题描述】:我想在 nest.js 控制器中使用 class-validator 来验证 body 有效负载。我的currency.dto.ts
文件是这样的:
import
IsNotEmpty,
IsString,
ValidateNested,
IsNumber,
IsDefined,
from 'class-validator';
class Data
@IsNotEmpty()
@IsString()
type: string;
@IsNotEmpty()
@IsNumber()
id: number;
export class CurrencyDTO
@ValidateNested( each: true )
@IsDefined()
data: Data[];
在我的 nest.js 控制器中,我是这样使用它的。
@Post()
@UseGuards(new AuthTokenGuard())
@UsePipes(new ValidationPipe())
addNewCurrency(@Req() req, @Body() data: CurrencyDTO)
console.log('data', data);
我的验证管道类是这样的:
import
PipeTransform,
Injectable,
ArgumentMetadata,
BadRequestException,
HttpException,
HttpStatus,
from '@nestjs/common';
import validate, IsInstance from 'class-validator';
import plainToClass, Exclude from 'class-transformer';
@Injectable()
export class ValidationPipe implements PipeTransform<any>
async transform(value: any, metadata: ArgumentMetadata)
if (value instanceof Object && this.isEmpty(value))
throw new HttpException(
`Validation failed: No Body provided`,
HttpStatus.BAD_REQUEST,
);
const metatype = metadata;
if (!metatype || !this.toValidate(metatype))
return value;
const object = plainToClass(metatype, value);
const errorsList = await validate(object);
if (errorsList.length > 0)
const errors = [];
for (const error of errorsList)
const errorsObject = error.constraints;
const isNotEmpty = errorsObject;
if (isNotEmpty)
const parameter = isNotEmpty.split(' ')[0];
errors.push(
title: `The $parameter parameter is required.`,
parameter: `$parameter`,
);
if (errors.length > 0)
throw new HttpException( errors , HttpStatus.BAD_REQUEST);
return value;
private toValidate(metatype): boolean
const types = [String, Boolean, Number, Array, Object];
return !types.find(type => metatype === type);
private isEmpty(value: any)
if (Object.keys(value).length > 0)
return false;
return true;
此验证管道适用于除嵌套对象之外的所有对象。知道我在这里做错了什么吗? 我的身体载荷是这样的:
"data": [
"id": 1,
"type": "a"
]
【问题讨论】:
【参考方案1】:尝试使用@Type
指定嵌套类型:
import Type from 'class-transformer';
export class CurrencyDTO
@ValidateNested( each: true )
@Type(() => Data)
data: Data[];
对于要验证的嵌套类型,它必须是类的实例,而不仅仅是普通数据对象。使用@Type
装饰器,当在VaildationPipe
中调用plainToClass
时,您告诉class-transformer 为给定属性实例化一个类。
如果您使用的是内置的ValidationPipe
,请确保您已设置选项transform: true
。
【讨论】:
出于任何原因,此解决方案对我不起作用。我按照你说的做了,但是没有用。 我已经尝试过了,它对我有用。 :-/ 没有更具体的信息,我帮不了你。也许打开一个新问题并添加您的代码?!我去看看。 我刚开了一个新帖子,如果你能看一下,我将不胜感激。 我会补充。该类验证器不需要此 \@Type 注释。这就是nestjs 的工作方式。它总是在你的 DTO 上使用 class-transformer,而 class-transformer 需要 \@Type 注释。 @LeonardoEmilioDominguez 尝试将两个类放在同一个文件中,并确保嵌套类首先出现(应该在顶部),顺序很重要。如您所见,数据出现在问题中的 DataDTO 之前。【参考方案2】:至少在我的情况下,接受的答案需要更多信息。照原样,如果请求中不存在密钥 data
,验证将不会运行。要获得完整的验证,请尝试:
@IsDefined()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => CreateOrganizationDto)
@ApiProperty()
organization: CreateOrganizationDto;
【讨论】:
以上是关于在 nest.js 控制器中使用类验证器验证嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章
使用 class-validator 和 Nest.js 验证对象数组
Nest.js 中使用 @nestjs/passport 的可选身份验证