Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/414.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript NestJs:如何使身体输入形状不同于实体';什么是DTO?_Javascript_Node.js_Typescript_Serialization_Nestjs - Fatal编程技术网

Javascript NestJs:如何使身体输入形状不同于实体';什么是DTO?

Javascript NestJs:如何使身体输入形状不同于实体';什么是DTO?,javascript,node.js,typescript,serialization,nestjs,Javascript,Node.js,Typescript,Serialization,Nestjs,我的照片和标签对象的DTO如下所示: export class PhotoDto { readonly title: string readonly file: string readonly tags: TagDto[] } export class TagDto { readonly name: string } 我在我的photo.service.ts中使用phototo,并最终在photo.controller.ts中创建照片: // In photo

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

export class PhotoDto {
    readonly title: string
    readonly file: string
    readonly tags: TagDto[]
}

export class TagDto {
    readonly name: string
}
我在我的
photo.service.ts
中使用
phototo
,并最终在
photo.controller.ts
中创建照片:

// 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> {
   // ...
}
如何更改
主体的输入形状以接受此结构

{
   "title": "Photo Title",
   "file": "/some/path/file.jpg",
   "tags": ["holiday", "memories"]
}
我尝试创建了两个不同的DTO,一个是
createPhotoTo
和一个
InputPhotoTo
,一个用于控制器中所需的输入形状,另一个用于服务和实体,但这最终非常混乱,因为在这两个DTO之间进行转换需要大量工作

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

将DTO更新为

将类导出到{
只读标题:字符串
只读文件:字符串
只读标记:数组
}

它会将API结构更改为

{
“标题”:“照片标题”,
“文件”:“/some/path/file.jpg”,
“标签”:[“假日”、“回忆”]
}


当前,您的tags属性是类型为TagDto的对象数组,请将tags属性更改为字符串数组。

您可以创建一个
嵌套
自定义装饰器,将输入数据转换为DTO对象

export const ConvertToCreateCatDto = createRouteParamDecorator((data, req): CreateCatDto => { // `createParamDecorator` for nest old version
    if (req.body.tags.every(value => typeof value === "string")) { // if input tags is a string[]
        req.body.tags = (req.body.tags as string[]).map<TagDto>((tag) => {
            return { // convert to TagDto
                name: tag + ""
            }
        });
    }
    let result = new CreateCatDto(req.body);
    // TODO: validate `result` object
    return result;
});
最后,在控制器中使用
@ConvertToCreateCatDto
而不是
@Body

// In photo.controller.ts
@Post()
async create(@ConvertToCreateCatDto() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
   //...
}
//在photo.controller.ts中
@Post()
异步创建(@ConvertToCreateCatDto()createPhotoTo:PhotoTo):承诺{
//...
}

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

1) 将
ValidationPipe
添加到控制器:

@UsePipes(new ValidationPipe({ transform: true }))
@Post()
async create(@Body() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
   // ...
}
// In photo.controller.ts
@Post()
async create(@ConvertToCreateCatDto() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
   //...
}
@UsePipes(new ValidationPipe({ transform: true }))
@Post()
async create(@Body() createPhotoDto: PhotoDto): Promise<PhotoEntity> {
   // ...
}
// 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[]
}