Validate nested objects using class validator and nestjs Validate nested objects using class validator and nestjs typescript typescript

Validate nested objects using class validator and nestjs


You are expecting positions: [1] to throw a 400 but instead it is accepted.

According to this Github issue, this seems to be a bug in class-validator. If you pass in a primitive type (boolean, string, number,...) or an array instead of an object, it will accept the input as valid although it shouldn't.


I don't see any standard workaround besides creating a custom validation decorator:

import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';export function IsNonPrimitiveArray(validationOptions?: ValidationOptions) {  return (object: any, propertyName: string) => {    registerDecorator({      name: 'IsNonPrimitiveArray',      target: object.constructor,      propertyName,      constraints: [],      options: validationOptions,      validator: {        validate(value: any, args: ValidationArguments) {          return Array.isArray(value) && value.reduce((a, b) => a && typeof b === 'object' && !Array.isArray(b), true);        },      },    });  };}

and then use it in your dto class:

@ValidateNested({ each: true })@IsNonPrimitiveArray()@Type(() => PositionDto)positions: PositionDto[];


for me, I would able to validate nested object with 'class-transformer'

import { Type } from 'class-transformer';

full example:

import {  MinLength,  MaxLength,  IsNotEmpty,  ValidateNested,  IsDefined,  IsNotEmptyObject,  IsObject,  IsString,} from 'class-validator';import { Type } from 'class-transformer';class MultiLanguageDTO {  @IsString()  @IsNotEmpty()  @MinLength(4)  @MaxLength(40)  en: string;  @IsString()  @IsNotEmpty()  @MinLength(4)  @MaxLength(40)  ar: string;}export class VideoDTO {  @IsDefined()  @IsNotEmptyObject()  @IsObject()  @ValidateNested()  @Type(() => MultiLanguageDTO)  name!: MultiLanguageDTO;}