当我需要验证数组的内容时,NestJS 中的 ValidationPipe 出现问题
Problems with ValidationPipe in NestJS when I need to validate the contents of an array
我的客户端用户可以输入零个或多个地址。我的问题是,如果他输入一个地址,有些字段需要是强制性的。
user.controller.ts
@Post()
@UsePipes(ValidationPipe)
async createUser(
@Body() createUser: CreateUserDto,
) {
return await this.service.saveUserAndAddress(createUser);
}
创建-user.dto.ts
export class CreateUserDto {
@IsNotEmpty({ message: 'ERROR_REQUIRED_FULL_NAME' })
fullName?: string;
@IsNotEmpty({ message: 'ERROR_REQUIRED_PASSWORD' })
password?: string;
@IsNotEmpty({ message: 'ERROR_REQUIRED_EMAIL' })
@IsEmail({}, { message: 'ERROR_INVALID_EMAIL' })
email?: string;
...
addresses?: CreateUserAddressDto[];
}
创建用户-address.dto.ts
export class CreateUserAddressDto {
...
@IsNotEmpty()
street: string;
...
}
CreateUserDto
数据被正确验证并生成 InternalServerErrorResponse
,但是当我的数组中有某些项目时 CreateUserAddressDto
数据未被验证。知道如何进行此验证吗?
您正在尝试做的是 - 基本上向开箱即用的原始验证器添加逻辑 nest - 又名 - 定义自定义验证器。
这可以通过使用 class 验证器提供的两个 classes ValidatorConstraint
和 ValidatorConstraintInterface
来完成。
为了对此进行排序,将传入的输入/俱乐部任何您想要立即验证的数据转换为对象 - 使用 nestjs 中的管道或将其作为对象发送到 API 调用本身,然后在其上附加一个验证器。
定义自定义验证器:
import { ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';
/**
* declare your custom validator here
*/
@ValidatorConstraint({ name: 'MyValidator', async: false })
export class MyValidator implements ValidatorConstraintInterface {
/** return true when tests pass **/
validate(incomingObject: myIncomingDataInterface) {
try {
// your logic regarding what all is required in the object
const output = someLogic(incomingObject);
return output;
} catch (e) {
return false;
}
}
defaultMessage() {
return 'Address update needs ... xyz';
}
}
一旦你定义了它,请根据你的项目结构将它安全地保存在某个地方。现在你只需要在你想进行验证时调用它。
在数据传输对象中,
// import the validator
import { Validate } from 'class-validator';
import { MyValidator } from './../some/safe/place'
export class SomeDto{
@ApiProperty({...})
@Validate(MyValidator)
thisBecomesIncomingObjectInFunction: string;
}
就这么简单。
Nest fw 使用 class-transformer
将 json 转换为 class 对象。如果它不是原始值,则必须为子属性设置正确的类型。而你的属性是一个数组,你必须配置告诉 class-validator
它是一个数组,并在每个项目上进行验证。
让我们更新一下CreateUserDto
import { Type } from 'class-transformer';
import { ..., ValidateNested } from 'class-validator';
export class CreateUserAddressDto {
...
@ValidateNested({ each: true })
@Type(() => CreateUserAddressDto)
addresses?: CreateUserAddressDto[];
...
}
我的客户端用户可以输入零个或多个地址。我的问题是,如果他输入一个地址,有些字段需要是强制性的。
user.controller.ts
@Post()
@UsePipes(ValidationPipe)
async createUser(
@Body() createUser: CreateUserDto,
) {
return await this.service.saveUserAndAddress(createUser);
}
创建-user.dto.ts
export class CreateUserDto {
@IsNotEmpty({ message: 'ERROR_REQUIRED_FULL_NAME' })
fullName?: string;
@IsNotEmpty({ message: 'ERROR_REQUIRED_PASSWORD' })
password?: string;
@IsNotEmpty({ message: 'ERROR_REQUIRED_EMAIL' })
@IsEmail({}, { message: 'ERROR_INVALID_EMAIL' })
email?: string;
...
addresses?: CreateUserAddressDto[];
}
创建用户-address.dto.ts
export class CreateUserAddressDto {
...
@IsNotEmpty()
street: string;
...
}
CreateUserDto
数据被正确验证并生成 InternalServerErrorResponse
,但是当我的数组中有某些项目时 CreateUserAddressDto
数据未被验证。知道如何进行此验证吗?
您正在尝试做的是 - 基本上向开箱即用的原始验证器添加逻辑 nest - 又名 - 定义自定义验证器。
这可以通过使用 class 验证器提供的两个 classes ValidatorConstraint
和 ValidatorConstraintInterface
来完成。
为了对此进行排序,将传入的输入/俱乐部任何您想要立即验证的数据转换为对象 - 使用 nestjs 中的管道或将其作为对象发送到 API 调用本身,然后在其上附加一个验证器。
定义自定义验证器:
import { ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';
/**
* declare your custom validator here
*/
@ValidatorConstraint({ name: 'MyValidator', async: false })
export class MyValidator implements ValidatorConstraintInterface {
/** return true when tests pass **/
validate(incomingObject: myIncomingDataInterface) {
try {
// your logic regarding what all is required in the object
const output = someLogic(incomingObject);
return output;
} catch (e) {
return false;
}
}
defaultMessage() {
return 'Address update needs ... xyz';
}
}
一旦你定义了它,请根据你的项目结构将它安全地保存在某个地方。现在你只需要在你想进行验证时调用它。
在数据传输对象中,
// import the validator
import { Validate } from 'class-validator';
import { MyValidator } from './../some/safe/place'
export class SomeDto{
@ApiProperty({...})
@Validate(MyValidator)
thisBecomesIncomingObjectInFunction: string;
}
就这么简单。
Nest fw 使用 class-transformer
将 json 转换为 class 对象。如果它不是原始值,则必须为子属性设置正确的类型。而你的属性是一个数组,你必须配置告诉 class-validator
它是一个数组,并在每个项目上进行验证。
让我们更新一下CreateUserDto
import { Type } from 'class-transformer';
import { ..., ValidateNested } from 'class-validator';
export class CreateUserAddressDto {
...
@ValidateNested({ each: true })
@Type(() => CreateUserAddressDto)
addresses?: CreateUserAddressDto[];
...
}