Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate each Map<string, number> value using class-validator

I'm trying to perform simple validation on a JSON input, modelled by one of my DTOs. One of the object properties is of type Map<string, number>. an example input:

{
  "type": "CUSTOM",
  "is_active": true,
  "current_plan_day": 1,
  "custom_warmup_plan": {
    "1": 123,
    "2": 456
}

On my controller I'm using a DTO to specify the body type. the class, together with class-validator decorators is this:

    export class CreateWarmupPlanRequestDto {
      @IsEnum(WarmupPlanType)
      type: string;
    
      @IsOptional()
      @IsNumber({ allowInfinity: false, allowNaN: false, maxDecimalPlaces: 0 })
      @IsPositive()
      hard_cap: number | null;
    
      @IsBoolean()
      is_active: boolean;
    
      @IsNumber({ allowInfinity: false, allowNaN: false, maxDecimalPlaces: 0 })
      @IsPositive()
      current_plan_day: number;
    
      @IsOptional()
      @IsNumber({ allowInfinity: false, allowNaN: false, maxDecimalPlaces: 0 })
      @IsPositive()
      previous_plan_day: number | null;
    
      @IsOptional()
      @IsNumber({ allowInfinity: false, allowNaN: false, maxDecimalPlaces: 0 }, { each: true })
      @IsPositive({ each: true })
      custom_warmup_plan: Map<string, number>;  // PROBLEM HERE
    }

I'm looking to validate each value of custom_warmup_plan to be an existing positive integer. Validation of the other properties of the object works just fine and as expected, but for my example input I keep getting errors (2 error messages, joined):

{
    "message": "each value in custom_warmup_plan must be a positive number. |#| each value in custom_warmup_plan must be a number conforming to the specified constraints",
    "statusCode": 400,
    "timestamp": "2021-07-29T13:18:29.331Z",
    "path": "/api/warmup-plan/bc4c3f0e-8e77-46de-a46a-a908edbdded5"
}

Documentation for this seems to be pretty straight forward, but I just cant get it to work. I've also played around with a simple Map<string, string> and the @IsString(each: true) validator, but that does not seem to work either.

any ideas?

versions:

"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/mapped-types": "^1.0.0",
"@nestjs/platform-express": "^8.0.0",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
like image 880
Maoration Avatar asked Aug 11 '26 11:08

Maoration


1 Answers

It is necessary to convert plain object to map. Use Transform decorator from class-transformer

@IsOptional()
@IsNumber(undefined, { each: true })
@Transform(({ value }) => new Map(Object.entries(value)))
prop?: Map<string, number>;
like image 136
berkantbegdilili Avatar answered Aug 14 '26 11:08

berkantbegdilili



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!