NodeJS NestJs -使用具有2个主体类选项的类验证器验证请求主体

ua4mk5z4  于 2023-02-03  发布在  Node.js
关注(0)|答案(3)|浏览(188)

我有一个rest调用,它可能接收类型classA或classB的主体。我需要将它作为2个不同的类。示例-

// classes -
class ClassA {
    @IsString()
    @Length(1, 128)
    public readonly name: string;
    @IsString()
    @Length(1, 128)
    public readonly address: string;
}

class ClassB {
    @IsString()
    @Length(1, 10)
    public readonly id: string;
}

// my request controller - 

    @Post('/somecall')
    public async doSomething(
        @Body(new ValidationPipe({transform: true})) bodyDto: (ClassA | ClassB) // < not validating any of them..
    ): Promise<any> {
// do something
    }

问题是,当有多个类时,body不被验证。
我如何使用2个或多个类,并使用类验证器验证它们?* 我不想使用同一个类.. *
谢谢大家:)

olhwl3o2

olhwl3o21#

  • 我不想用同一个类 *

那么这就不可能了,至少Nest内置的ValidationPipe不可能。Typescript不反映联合、交集或其他类型的泛型类型,所以这个参数没有返回元数据,如果没有可操作的元数据,Nest将跳过管道。
你可以创建一个自定义管道来为你做验证,如果你有两个类型,你可能必须这样做。你仍然可以在类内部调用适当的class-transformerclass-validator方法。

yzckvree

yzckvree2#

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { of } from 'rxjs';

@Injectable()
export class CheckTypeInterceptor implements NestInterceptor {
    constructor() {}

    async intercept(context: ExecutionContext, next: CallHandler) /*: Observable<any>*/ {
        const httpContext = context.switchToHttp();
        const req = httpContext.getRequest();
        const bodyDto = req.body.bodyDto;

        // Need Update below logic
        if (bodyDto instanceof ClassA || bodyDto instanceof ClassB) {
            return next.handle();
        }

        // Return empty set
        return of([]);
    }
}
@UseInterceptors(CheckTypeInterceptor)
export class ApiController {
   ...
}
0sgqnhkj

0sgqnhkj3#

遇到了类似的情况,我必须验证一些联合类型请求。
我最终得到的解决方案是一个自定义管道,正如JayMcDoniel在这里建议的那样。逻辑会根据您正在处理的请求主体而变化,但是根据问题,下面的方法可能有效

定制管道

import { ArgumentMetadata, BadRequestException, Inject, Scope } from "@nestjs/common";
import { PipeTransform } from "@nestjs/common";
import { plainToInstance } from "class-transformer";
import { validate } from "class-validator";
import { ClassADto } from '../repository/data-objects/class-a.dto';
import { ClassBDto } from '../repository/data-objects/class-b.dto';

export class CustomPipeName implements PipeTransform<any> {

    async transform(value: any,  { metatype, type }: ArgumentMetadata): Promise<any> {

        if (type === 'body') {
            const classA = plainToInstance(ClassADto, value);
            const classB = plainToInstance(ClassBDto, value);
            const classAValidationErrors = await validate(classA);
            const classBValidationErrors = await validate(classB);
            if (classAValidationErrors.length > 0 && classBValidationErrors.length > 0) {
                throw new BadRequestException('some fancy info text');
            }
        }
        return value;
    }
}

控制器使用情况:

@Post('/somecall')
    public async doSomething(
        @Body(new CustomePipeName()) bodyDto: (ClassA | ClassB)
    ): Promise<any> {
// do something
    }

相关问题