有没有一种方法可以将默认值设置为缺少/可选的JSON属性?

时间:2019-01-03 18:25:04

标签: node.js json typescript nestjs

我使用NodeJ / NestJs构建RESTful服务。我创建了一些与请求JSON相匹配的对象。这些对象中有一些可选属性,但是如果客户端不通过JSON发送默认值,我想为它们设置默认值。

达到目标的最佳方法是什么?

这是我与JSON匹配的DTO。

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。 >

2 个答案:

答案 0 :(得分:4)

仅当RequestDto实际上被实例化为类时,您的默认值才适用。由于您已经在使用class-validator进行验证,因此可以使用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();

答案 1 :(得分:1)

好的,没有OP的代码样本,此响应的保真度可能需要改进。就是说,“ nest-y”方式是通过TransformPipe实现的。

他们给出的规范示例是针对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;
  }
}