網站搜尋

node.js - NestJS - 根據某個屬性有條件地驗證請求主體


我正在嘗試找到一種使用 DTO 驗證 body 的好方法(使用出色的 class-validator 和 class-transformer 庫)。它運作得非常好,即使是對於巢狀結構也很有效,但在我的情況下,我希望根據某些條件來設置 body 屬性。

可能有助於理解的範例:

讓我們假設我的身體應該總是有 selectedCategory。根據該欄位,內容可以來自類別 1,該類別包含 prop1,或者來自類別 2,該類別包含 prop2。

我不想允許兩者都為空,我真的希望根據 selectedCategory 必須要麼定義 prop1,要麼定義 prop2。

我認為我可以使用一個管道,但那麼我該如何指定要使用的正確 DTO 呢?

我建立了一個包含所有常用屬性的「基底」類別,並有幾個其他類別繼承自它。

我可以根據屬性 selectedCategory 手動實例化這個管道,那將是理想的,但我完全不知道作為管道的第二個參數(metadata)該傳入什麼。

感謝你的幫助。

答案#1

你有嘗試過使用群組嗎?與其擁有多個 DTO,不如只建立一個 DTO。每個屬性都會被分配到一個或多個群組:

@Min(12, {groups: ['registration', 'update']})
age: number;
@Length(2, 20, {groups: ['registration']})
name: string;

然後你可以有條件地將這些群組傳遞給類轉換器/驗證器:

@Injectable()
export class ConditionalValidationPipe implements PipeTransform {
  async transform(entity: any, metadata: ArgumentMetadata) {
    // Dynamically determine the groups
    const groups = [];
    if (entity.selectedCategory === 1) {
      groups.push('registration');
    }

    // Transform to class with groups
    const entityClass = plainToClass(EntityDto, entity, { groups })

    // Validate with groups
    const errors = await validate(entityClass, { groups });
    if (errors.length > 0) {
      throw this.createError(errors);
    }
    return entityClass;
  }
}

答案#2

你試過使用 ValidateIf 陳述式嗎?

您可以對 props1 或 props2 進行多重驗證,並在 selectedCategory 分別為「category 1」或「category 2」時應用它們。