本文介绍了NestJs:如何让 Body 输入形状与实体的 DTO 不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的照片和标签对象有 DTO,如下所示:

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
}

我在我的 photo.service.ts 中使用 PhotoDto 并最终在 photo.controller.ts 中用于创建照片:

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> {
   // ...
}

但是,API 主体中的输入应具有以下结构:

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

如何更改 Body 的输入形状以接受此结构?

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

我尝试创建 2 个不同的 DTO,一个 CreatePhotoDto 和一个 InputPhotoDto,一个用于控制器中所需的输入形状,另一个用于服务和实体,但这最终会非常混乱,因为在 2 个 DTO 之间进行转换需要做很多工作.

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.

使用与 Post 请求的 Body 不同的输入形状,然后将其转换为实体所需的 DTO 的正确方法是什么?

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?

推荐答案

您可以使用 ValidationPipe() 的自动转换:

You can use the auto-transform of the ValidationPipe():

1) 将 ValidationPipe 添加到您的控制器:

1) Add the ValidationPipe to your controller:

@UsePipes(new ValidationPipe({ transform: true }))
@Post()
async create(@Body() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
   // ...
}

2) 将 @Transform 添加到您的 PhotoDto:

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

这篇关于NestJs:如何让 Body 输入形状与实体的 DTO 不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 22:02