Search code examples
nestjsclass-validatorclass-transformer

How to validate nested plain objects by a sub-DTO with class-validator, class-transformer in NestJS


I've been investigating the topic for a long time. I see the ready solution is absent that works well in NestJS because transformation does not work before validation. If we enable transformation in the validation pipe, it transforms after validation before passing into the controller. The decorator @ValidateNested() validates only instances of DTO. But from REST simple JSON comes without any transformation. @Type and @Transform decorators belong to the transformation process so they can not help. I am almost ready to create my solution with a custom validator. Stop me if a ready solution exists.

I see many similar questions in the StackOverflow. They all make the same mistake. They do not see two different processes validation and transformation. Somebody also suggested creating a custom decorator. Regards.


Solution

  • I think the assumptions made in this discussion are not entirely correct. The ValidationPipeline does run input data through class-transformer before validating it. Unfortunately, class-transformer doesn't know how to handle the property with the nested DTO. You'd have to add two more decorators to the parent DTO: @Type (from class-transformer and @ValidateNested from class-validator. This way, the transformer correctly transforms the nested property in to a class instance and the validator knows that it should validate it.

    The following sample is for GraphQL (code-first) but the same principals can be used in a REST API

    @InputType()
    class SomeInput {
      @Field()
      @MaxLength(32, { each: true})
      tags: string[]
    }
    
    @ArgsType()
    class SomeArgs {
      @Field()
      @Type(() => SomeInput)
      @ValidateNested()
      data: SomeInput
    }
    
    class Resolver {
      @Query
      updateTags(@Args(ValidationPipe) args: SomeArgs) {}
    }
    
    

    To reduce clutter in the code, you can use Decorator composition to only have a single decorator

    also see validating-nested-objects and working-with-nested-objects