3

I am trying to enforce a validation on each item of an array.

As per my understanding (please correct me if I am wrong), class-validator does not support direct validation of arrays. It requires us to create a wrapper class.

So, the following are the classes:

export class SequenceQuery {   
    @MinLength(10, {
        message: 'collection name is too short',
      })
    collection: string;
    identifier: string;
    count: number;
}
export class SequenceQueries{
    @ValidateNested({ each: true })
    queries:SequenceQuery[];
}

And the following is my controller:

  @Get("getSequence")
  async getSequence(@Body() query:SequenceQueries) {
    return await this.sequenceService.getNextSequenceNew(query)
  }

The following is the JSON that I am passing to the controller:

{"queries":  [
    {
        "collection": "A",
        "identifier": "abc",
        "count": 1
    },
    {
        "collection": "B",
        "identifier": "mno",
        "count": 5
    },
    {
        "collection": "C",
        "identifier": "xyz",
        "count": 25
    }
]}

But it doesn't seem to be working. It's not throwing any validation messages.

4 Answers 4

4

I got the solution to the problem.

I was supposed to change my wrapper class to :

export class SequenceQueries{
    @ValidateNested({ each: true })
    @Type(() => SequenceQuery) // added @Type
    queries:SequenceQuery[];
}

But I will leave the question open, just in case someone has an alternate solution as in not having to make a wrapper class.

Sign up to request clarification or add additional context in comments.

1 Comment

The type should be imported using nestjs class transformer
1

There is my complete solution/implementation in Nestjs

  1. First create my DTO Class
export class WebhookDto {
  @IsString()
  @IsEnum(WebHookType)
  type: string;

  @IsString()
  @IsUrl()
  url: string;

  @IsBoolean()
  active: boolean;
}

export class WebhookDtoArray {
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => WebhookDto)
  webhooks: WebhookDto[];
}
  1. Place my DTO Class in my Controller definition
  @MessagePattern('set_webhooks')
  async setWebhooks(
    @Payload('body') webhookDtoArray: WebhookDtoArray,
    @Payload() data,
  ): Promise<Store> {
    return this.storeManagementService.setWebhooks(
      data.userPayload.id,
      webhookDtoArray,
    );
  }
  1. An example in Postman of what the Body I should send
{
  "webhooks": [{
      "type": "InvoiceCreated",
      "url": "https://test.free.beeceptor.com",
      "active": true
    },
    {
      "type": "InvoiceSettled",
      "url": "https://test.free.beeceptor.com",
      "active": true
    },
    {
      "type": "InvoiceExpired",
      "url": "https://test.free.beeceptor.com",
      "active": true
    }
  ]
}

Comments

0

class-validator does support array validation you have just to add what you already did in @ValidateNested({ each: true }), you have only to add each to the collection element:

export class SequenceQuery {   
@MinLength(10, {
    each: true,
    message: 'collection name is too short',
  })
collection: string;
identifier: string;
count: number;

}

source : Validation Array

Comments

0

From Nest.js documentation:

To validate the array, create a dedicated class which contains a property that wraps the array, or use the ParseArrayPipe.

@Post()
createBulk(
  @Body(new ParseArrayPipe({ items: CreateUserDto }))
  createUserDtos: CreateUserDto[],
) {
  return 'This action adds new users';
}

So, if you do not want to create a wrapper property - use ParseArrayPipe. Example Postman Body that can be used send with CreateUserDto proper validation:

[
    {
        "avatar": "http://href",
        "name": "Name"
    },
    {
        "avatar": "http://href2",
        "name": "Name2"
    },
]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.