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.