Alexander Burakevych
Alexander Burakevych

Reputation: 2436

ValidationPipe in NestJS for a key-value pair object

I have the following DTO object in my NestJS controller as part of the request body:

export class UserPropertiesDto {
  [key: string]: boolean;
}

E.g.: {campaignActive: true, metadataEnabled: false}

It's a key-value pair object, where the key is a unique string and its value is a boolean.

I want to apply class-validator annotations to ensure proper validations and transformations, but it keeps showing an error Decorators are not valid here:

export class UserPropertiesDto {
  @IsOptional()
  @IsString() // `key` should be a string
  @MaxLength(20) // `key` should have no more than 20 characters
  @IsBoolean() // `value` has to be a `boolean`
  [key: string]: boolean;
}

Could you, please, advice on the best way to do this:

Upvotes: 3

Views: 6216

Answers (2)

Ayoub Touba
Ayoub Touba

Reputation: 3007

I suggest you to work with a custom validator, I tried to do something work for you:

iskeyvalue-validator.ts

   import { ValidatorConstraint, ValidatorConstraintInterface, 
 ValidationArguments } 
 from 
  "class-validator";
   import { Injectable } from '@nestjs/common';

  @Injectable()
  @ValidatorConstraint({ async: true })
  export class IsKeyValueValidate implements ValidatorConstraintInterface {



    async validate(colmunValue: Object, args: ValidationArguments) {
      try {
         if(this.isObject(colmunValue))
              return false; 

       var isValidate = true;
       Object.keys(colmunValue)
       .forEach(function eachKey(key) {  
          if(key.length > 20 || typeof key  != "string" || typeof colmunValue[key] != 
        "boolean")
          {
            isValidate = false;
          }
        });
       return isValidate ;


        } catch (error) {
     console.log(error);
      } 

       }

isObject(objValue) {
return objValue && typeof objValue === 'object' && objValue.constructor === Object;
   }

    defaultMessage(args: ValidationArguments) { // here you can provide default error 
      message if validation failed
     const params = args.constraints[0];
  if (!params.message)
     return `the ${args.property} is not validate`;
  else
     return params.message;
   }
   }

To implement it you have to add IsKeyValueValidate in the module providers :

providers: [...,IsKeyValueValidate],

and in your Dto:

   @IsOptional()
  @Validate(IsKeyValueValidate, 
    [ { message:"Not valdiate!"}] )
  test: Object;

Upvotes: 2

Yevhenii
Yevhenii

Reputation: 1713

I'd advice to pay attention on custom validator. During validation it have access to all properties and values of the validated object.

All validation arguments you can pass as a second parameter and use them inside of validator to control flow.

export class Post {
 
    @Validate(CustomTextLength, {
        keyType: String,
        maxLength: 20
       ...
    })
    title: string;
 
}

Upvotes: 1

Related Questions