Javascript NestJs:如何使身体输入形状不同于实体';什么是DTO?
我的照片和标签对象的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
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[]
}