Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
54
rated 0 times [  58] [ 4]  / answers: 1 / hits: 12447  / 5 Years ago, mon, april 1, 2019, 12:00:00

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?


More From » node.js

 Answers
39

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[]
}

[#8208] Friday, March 29, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
lailab

Total Points: 706
Total Questions: 102
Total Answers: 95

Location: Falkland Islands
Member since Mon, Jul 13, 2020
4 Years ago
;