Node.js 有没有办法将默认值设置为缺少/可选的JSON属性?
我使用NodeJs/NestJs构建RESTful服务。我创建了一些与请求JSON匹配的对象。在这些对象中有一些可选属性,但是如果客户端不通过JSON发送它们,我想为它们设置默认值 实现目标的最佳方式是什么 这是我要与JSON匹配的DTONode.js 有没有办法将默认值设置为缺少/可选的JSON属性?,node.js,json,typescript,nestjs,Node.js,Json,Typescript,Nestjs,我使用NodeJs/NestJs构建RESTful服务。我创建了一些与请求JSON匹配的对象。在这些对象中有一些可选属性,但是如果客户端不通过JSON发送它们,我想为它们设置默认值 实现目标的最佳方式是什么 这是我要与JSON匹配的DTO import { IsDefined, IsNumber, Min } from 'class-validator'; import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/sw
import { IsDefined, IsNumber, Min } from 'class-validator';
import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
export class RequestDto {
@IsDefined()
@IsNumber()
@Min(0)
@ApiModelProperty({description: 'The current age.'})
public CurrentAge: number;
@ApiModelPropertyOptional({description: 'The existing saving amount.'})
public ExistingSavingAmount: number = 0;
}
这是我的NestJs控制器
import { Controller, Post, Body, Param } from '@nestjs/common';
import { RequestDto } from './Dto/Request.Dto';
import { ApiResponse, ApiOperation } from '@nestjs/swagger';
@Controller('mycontroller')
export class MyController {
@Post('MyEndPoint')
@ApiOperation({ title: 'Do something' })
@ApiResponse({ status: 201, description: 'Something is done' })
public doSomething(@Body() request: RequestDto) {
// do more jobs
}
}
我启动服务,并将下面的JSON发布到我的终点
{
"CurrentAge": 40,
}
在我的控制器中,我看到
ExistingSavingAmount
的值不是0而是空的。但是如果我直接实例化RequestDto
,我可以看到ExistingSavingAmount
的值是0。好的,没有OP的代码样本,这个响应的保真度可能需要提高。也就是说,“nest-y”实现这一点的方法是通过
他们给出的典型示例是ParseIntPipe:
import { Injectable, BadRequestException} from '@nestjs/common';
@Injectable()
export class ParseIntPipe {
transform(value, metadata) {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
在不知道默认值的情况下,我将假设它类似于一个产品,您希望默认一些内容,并将一些内容作为空字符串:
import { Injectable, BadRequestException} from '@nestjs/common';
// we will assume you have your own validation for the non-optional bits
const optionalDefaults = {
description: '',
category: 'Miscelleneous'
}
@Injectable()
export class ProductDefaultsPipe {
transform(value, metadata) {
const val = Object.assign(optionalDefaults, value);
return val;
}
}
现在,这意味着您可能正在使用提供模式和模型定义的东西(比如Joi或Mongoose)。如果是,那么我建议在该模式中设置所有默认值和验证,然后在TransformPipe中应用该模式,而不是编写大量自定义代码。例如,如果您有一个ProductSchema,这将适用于您:
@Injectable()
export class ProductDefaultsPipe {
async transform(value, metadata) {
const val = new Product(value);
const isValid = await val.validate();
if (!isValid) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
只有当
RequestDto
实际实例化为类时,才会应用默认值。因为您已经在使用类验证器进行验证,所以可以使用classTransformer.plainToClass()
来实例化该类
如果您使用的是内置的ValidationPipe
,则可以使用{transform:true}
选项来自动实例化RequestDto
类:
@UsePipes(new ValidationPipe({ transform: true }))
@Post('MyEndPoint')
public doSomething(@Body() request: RequestDto) {
或作为全局管道:
async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
app.useGlobalPipes(new ValidationPipe({ transform: true }));
await app.listen(3000);
}
bootstrap();
你能举一个你现有的端点为例吗,甚至可以用JSON示例来告诉我们你的意思吗?@Paul我已经用示例代码更新了我的帖子。非常感谢你的输入。进一步的问题是,如果不使用
classTransformer.plainToClass()
或@usepippes(newvalidationpipe({transform:true}))
,DTO类就不会被实例化,那么它从何而来?由于我来自C#后台,因此在本例中,对象是从JSON反序列化的,因此它由序列化程序实例化。在这种情况下,JavaScript/TypeScript非常不同?如果没有类转换器,它将不会从JSON反序列化,而是保持一个普通的JavaScript对象。因为这发生在运行时,所以没有类型检查。事实上,在运行时您不会有RequestDto对象,而是会有一个普通对象(希望没有人检查)符合RequestDto的接口。