Tengo una situación en la que el usuario de mi cliente puede ingresar cero o varias direcciones. Mi problema es que si ingresa una dirección, algunos campos deben ser obligatorios.
usuario.controlador.ts
@Post() @UsePipes(ValidationPipe) async createUser( @Body() createUser: CreateUserDto, ) { return await this.service.saveUserAndAddress(createUser); }crear-usuario.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[]; }crear-dirección-de-usuario.dto.ts
export class CreateUserAddressDto { ... @IsNotEmpty() street: string; ... } Los datos de CreateUserDto se validan correctamente y generan InternalServerErrorResponse , pero los datos de CreateUserAddressDto no se validan cuando hay algún elemento en mi matriz. ¿Alguna idea de cómo puedo hacer esta validación?
Lo que está tratando de hacer es, básicamente, agregar lógica a los validadores primitivos provistos de fábrica con nest, es decir, definir un validador personalizado.
Esto se puede hacer usando las dos clases ValidatorConstraint y ValidatorConstraintInterface proporcionadas por el validador de clases.
Para ordenar esto, transforme la entrada entrante / club cualquier dato que desee validar de inmediato en un objeto, ya sea usando una canalización en nestjs o envíelo como un objeto en la llamada API, luego adjunte un validador encima de él .
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'; } }Una vez que haya definido esto, manténgalo seguro en algún lugar según la estructura de su proyecto. Ahora solo necesita llamarlo cuando quiera poner esta validación.
En el objeto de transferencia de datos ,
// import the validator import { Validate } from 'class-validator'; import { MyValidator } from './../some/safe/place' export class SomeDto{ @ApiProperty({...}) @Validate(MyValidator) thisBecomesIncomingObjectInFunction: string; }Tan simple como eso.
Nest fw usa class-transformer para convertir un json en un objeto de clase. Debe establecer el tipo correcto para el subatributo si no es un valor primitivo. Y su atributo es una matriz, debe configurar para decirle class-validator que es una matriz y validar en cada elemento.
CreateUserDto
import { Type } from 'class-transformer'; import { ..., ValidateNested } from 'class-validator'; export class CreateUserAddressDto { ... @ValidateNested({ each: true }) @Type(() => CreateUserAddressDto) addresses?: CreateUserAddressDto[]; ... }