Home > Blockchain >  How to validate dynamic property-name on REST API in nest.js app?
How to validate dynamic property-name on REST API in nest.js app?

Time:11-25

Task is to validate payload in nest.js app before managing one. Each payload can contain tag objects (1 - 11). Every tag object can have only one property and value (property determined by request)

Tag objects should be validated:

  • property should be a string with any characters accept : and size in 1-255
  • value should be a string with size in 1-255

Task looks like simple one. But I have no idea how to validate dynamically constructed properties in Tag objects.

The DTOs are (validation configured using class-validator):

import {
  ArrayMaxSize,
  ArrayMinSize,
  IsArray,
  IsDefined,
  IsNotEmpty,
  IsObject,
  IsString,
  Matches,
  MinLength,
  ValidateNested
} from 'class-validator';


export class Payload {
...
  @IsArray()
  @ArrayMinSize(1)
  @ArrayMaxSize(11)
  @ValidateType(() => Tag)
  @ValidateNested()
  @ApiProperty()
  tags: Tag[];
}

To make Tag flexible (because unknown property name) it made like Map extension

export class Tag extends Map<string, string>{
}

or single field object

export class Tag {
  [key: string]: string;
}

How to manage required validation for each Tag?

(Regexp that excludes input with : is /^[^:] $/ and should be applied for key)

CodePudding user response:

I've got solution, but better than solution implementation compare possible approaches.

1 scenario is to put additional custom validation decorators on tags field

  @IsPropertyNameLength(1, 250,{ each: true })
  @IsPropertyNameMatches(/^[^:] $/,{ each: true })
  @IsPropertyNameString({ each: true })
  @IsKeyNameLength(1, 250,{ each: true })
  @IsKeyNameMatches(/\w |\d /,{ each: true })
  @IsKeyNameString({ each: true })
  tags: Tag[];

it might be good solution. Following this way we'd realise that decorator names do not bring enough information. Trying to make them more universal we can add more parameters. But this improvements can't change the fact that we ave validating not current or next level property. We do validation of property on next after next level (tags[] -> Tag -> theProperty).

2 scenrio is to manage validation on middleware layer. It might bring some difficulties if you want make reports same format and after similar flow as provided in class-validator but benefit is that we can spit validations on different methods constructing more complex validation tree. Also it would be easy for testing.

3 scenrio is to decline dynamic property names (if that's possible) and consider developing alternative model like

export class Tag {
  key: string;
  value: string;
}

it gives us chance using provided decorators from class-validator for our needs, for example

export class Tag {
  @Length(1, 250)
  @Matches(/^[^:] $/)
  key: string;
  @Length(1, 250)
  @Matches(/\w |\d /)
  value: string;
}

P.S.

I've managed my solution following 3rd way.

  • Related