使用 nest.js 控制器中的 class-validator 验证嵌套的 objects
validate nested objects using class-validator in nest.js controller
我想在 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);
}
我的验证管道class是这样的:
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;
}
}
除了嵌套 objects 之外,此验证管道对所有工作都很好。知道我在这里做错了什么吗?
我的 body 负载是这样的:
{
"data": [{
"id": 1,
"type": "a"
}]
}
尝试使用 @Type
:
指定嵌套类型
import { Type } from 'class-transformer';
export class CurrencyDTO {
@ValidateNested({ each: true })
@Type(() => Data)
data: Data[];
}
要验证嵌套类型,它需要是 class 的实例,而不仅仅是普通数据对象。使用 @Type
装饰器,当在 VaildationPipe
中调用 plainToClass
时,您告诉 class-transformer 为给定的 属性 实例化一个 class。
如果您使用的是内置 ValidationPipe
,请确保您已设置选项 transform: true
。
至少就我而言,接受的答案需要更多信息。照原样,如果请求中不存在键 data
,验证将不会 运行。要获得完整验证,请尝试:
@IsDefined()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => CreateOrganizationDto)
@ApiProperty()
organization: CreateOrganizationDto;
我想在 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);
}
我的验证管道class是这样的:
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;
}
}
除了嵌套 objects 之外,此验证管道对所有工作都很好。知道我在这里做错了什么吗? 我的 body 负载是这样的:
{
"data": [{
"id": 1,
"type": "a"
}]
}
尝试使用 @Type
:
import { Type } from 'class-transformer';
export class CurrencyDTO {
@ValidateNested({ each: true })
@Type(() => Data)
data: Data[];
}
要验证嵌套类型,它需要是 class 的实例,而不仅仅是普通数据对象。使用 @Type
装饰器,当在 VaildationPipe
中调用 plainToClass
时,您告诉 class-transformer 为给定的 属性 实例化一个 class。
如果您使用的是内置 ValidationPipe
,请确保您已设置选项 transform: true
。
至少就我而言,接受的答案需要更多信息。照原样,如果请求中不存在键 data
,验证将不会 运行。要获得完整验证,请尝试:
@IsDefined()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => CreateOrganizationDto)
@ApiProperty()
organization: CreateOrganizationDto;