I have DTOs for my Photo and Tag objects that look like this:
export class PhotoDto {
readonly title: string
readonly file: string
readonly tags: TagDto[]
}
export class TagDto {
readonly name: string
}
I use the PhotoDto
in my photo.service.ts
and eventually in the photo.controller.ts
for the creation of Photo:
// In photo.service.ts
async create(createPhotoDto: PhotoDto): Promise<PhotoEntity> {
// ...
return await this.photoRepo.create(createPhotoDto)
}
// In photo.controller.ts
@Post()
async create(@Body() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
// ...
}
However, the input in the Body of the API is expected to have this structure:
{
"title": "Photo Title",
"file": "/some/path/file.jpg",
"tags": [
{
"name": "holiday"
},
{
"name": "memories"
}
]
}
How can I change the input shape of the Body
to accept this structure instead?
{
"title": "Photo Title",
"file": "/some/path/file.jpg",
"tags": ["holiday", "memories"]
}
I have tried creating 2 different DTOs, a CreatePhotoDto
and an InputPhotoDto
, one for the desired input shape in the controller and one for use with the service and entity, but this ends up very messy because there is a lot of work with converting between the 2 DTOs.
What is the correct way to have a different input shape from the Body
of a Post
request and then have it turned into the DTO required for use by the entity?
You can use the auto-transform of the ValidationPipe()
:
1) Add the ValidationPipe
to your controller:
@UsePipes(new ValidationPipe({ transform: true }))
@Post()
async create(@Body() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
// ...
}
2) Add a @Transform
to your PhotoDto
:
// Transforms string[] to TagDto[]
const transformTags = tags => {
if (Array.isArray(tags)) {
return tags.map(tag => ({name: tag}))
} else {
return tags;
}
}
import { Transform } from 'class-transformer';
export class PhotoDto {
readonly title: string
readonly file: string
@Transform(transformTags, {toClassOnly: true})
readonly tags: TagDto[]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With