提问人:girish 提问时间:11/16/2023 最后编辑:girish 更新时间:11/17/2023 访问量:39
验证管道中的 Nestjs 序列化不起作用
Nestjs serialization in validation pipe not working
问:
我正在尝试将@Expose与类属性的别名一起使用,如下所示,但我在 camelCase 中得到了响应。
import { Expose } from 'class-transformer';
import { BaseResponse } from './base-response.class';
export class ValidationResponse extends BaseResponse {
@Expose({
name: 'SomeField',
})
someField: string;
@Expose({
name: 'AnotherField',
})
anotherField= string;
}
在有效负载验证失败的情况下,我从验证管道中使用 ValidationResponse 抛出一个错误的请求错误,如下所示。
错误的请求错误类
import { HttpException, HttpStatus } from '@nestjs/common';
export class BadRequestError extends HttpException {
constructor(response?: unknown) {
super(response, HttpStatus.BAD_REQUEST);
}
}
自定义验证管道
import { ArgumentMetadata, Inject, PipeTransform, UseInterceptors, ClassSerializerInterceptor } from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';
import { BadRequestError } from '../exceptions/bad-request.exception';
import { ErrorModel } from '../../common/classes/error-model.class';
import { ErrorCode } from '../../common/enums/error.enum';
import { ValidationResponse } from '../../common/classes/validation-response.class';
import { REQUEST } from '@nestjs/core'
import { CustomRequest } from 'src/common/classes/custom-request.class';
@UseInterceptors(ClassSerializerInterceptor)
export class CustomValidationPipe implements PipeTransform {
constructor(@Inject(REQUEST) protected readonly request: CustomRequest) { }
async transform(value: any, { metatype }: ArgumentMetadata) {
const object = plainToClass(metatype, value);
const errors = await validate(object, {
forbidUnknownValues: false,
});
if (errors.length) {
let errorResponse: ValidationResponse = new ValidationResponse();
errorResponse.someField= 'somevalue';
errorResponse.anotherField= 'anothervalue';
throw new BadRequestError(errorResponse);
}
return value;
}
}
我在控制器中将验证管道用于 POST API,如下所示
import { CustomValidationPipe } from 'custom-validation.pipe';
@UseInterceptors(ClassSerializerInterceptor)
export class SomeController {
@Post('test')
@HttpCode(200)
@ApiCreatedResponse({
type: SomeResponse,
})
async someFunction(
@Request()
request,
@Body(CustomValidationPipe)
body: SomeRequest,
): Promise<SomeResponse> {
// controller logic here
}
}
使用 @Expose 我试图将字段的大小写更改为 pascal 大小写,但是当我从管道获得响应时,它是驼峰大小写,因为该字段最初是在 ValidationResponse 类中定义的。也许我做错了什么。任何帮助都非常感谢。
答:
1赞
Jay McDoniel
11/17/2023
#1
至少默认情况下,它只对 的返回值起作用,而不是错误/异常或任何内容。如果你想添加它,你必须扩展类并添加一种方式来应对这种情况。对于您来说,只需将类设置为具有您想要的这些 pascal 大小写字段并在抛出异常时直接设置它们会更容易。ClassSerializerInterceptor
controller
thrown
.catchError()
ValidationResponse
另外,作为旁注,对管道自定义管道类不执行任何操作。它只影响这里的控制器,所以你可以摆脱它。@UseInterceptors()
评论
0赞
girish
11/17/2023
谢谢你的回答。我想走硬路并使用@Expose因为我有BaseResponse类,该类在ValidationResponse类中扩展,该类再次用于应用程序的其余部分,因此更改大小写将不是一种有效且干净的方法。您能否详细说明“您必须扩展类并向 .catchError() 添加一种方法”,或者一些基本代码才能开始?
0赞
Jay McDoniel
11/17/2023
您需要有自己的拦截器,并且在方法中具有 where 是一个接受并返回extends ClassSerializerInterceptor
intercept
return super.intercept(context).pipe(catchError(errorSerializationHandler))
errorSerializationHandler
Error
Observable<Record<string, unknown>>
评论