typescript 如何使用类转换器中的@Expose装饰器在NestJS中定义相同的响应输出字段名称?

yqyhoc1h  于 2023-03-04  发布在  TypeScript
关注(0)|答案(1)|浏览(257)

目前,我的实体定义如下:

export class ItemEntity implements Item {

  @PrimaryColumn()
  @IsIn(['product', 'productVariant', 'category'])
  @IsNotEmpty()
  itemType: string;

  @PrimaryColumn()
  @IsUUID()
  @IsNotEmpty()
  itemId: string;

  @OneToOne(() => ProductEntity, product => product.id, { nullable: true })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  producttItem: ProductEntity;

  @OneToOne(() => ProductVariantEntity, variant => variant.id, {
    nullable: true,
  })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  variantItem: ProductVariantEntity;

  @OneToOne(() => CategoryEntity, category => category.id, { nullable: true })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  categoryItem: CategoryEntity;
}

我添加了@Expose()装饰器,因为我希望能够返回productItemvariantItemcategoryItem中的一个,作为响应中的一个bundleItem字段,其中任何一个都可以有一个值,但不能有两个或三个值。
但是,当我在ItemEntity的控制器上执行GET时,我想要的效果只应用于第一项,而不是其他项:

[
    {
        "itemType": "category",
        "itemId": ""
        "bundleItem": {
            "categoryType": "Custom",
            "description": "First custom category",
            "id": "e00ad76c-95d3-4215-84b1-de17c7f1f82c",
            "name": "Category A",
            "updatedAt": "2023-02-24T08:49:22.913Z"
        }
    },
    {
        "itemType": "variant",
        "itemId": "",
        "bundletem": null
    }
]

我想把效果扩展到返回数组响应中的其他项。但目前,它们是null。本质上,我想让响应返回一个bundleItem字段,而不管itemType是什么类型,是productItemvariantItem,还是categoryItem。我可以使用'class-transformer来实现吗?
谢谢。

vltsax25

vltsax251#

你可以使用@Transform来实现这个目的,@Transform装饰器包含了一些你可以在转换过程中使用的参数,其中之一就是对象本身。

@Transform(({ value, key, obj, type }) => value)

下面的示例包含一个具有两个属性的对象,如果其中一个是nullundefined,则返回另一个

import {Exclude, Expose, Transform} from "class-transformer";

export class ExampleDto {
  constructor(partial: Partial<ExampleDto>) {
    Object.assign(this, partial);
  }

  @Expose()
  name: string;

  @Expose({ name: "new_property" })
  @Transform(({ value, key, obj, type }) => {
    return obj.property1 ?? obj.property2;
  })
  property1: string | null;

  @Exclude()
  property2: string | null;
}

主计长

@Get("example")
  @UseInterceptors(ClassSerializerInterceptor)
  getExample(): ExampleDto {
    return new ExampleDto({
      name: "Name",
      property2: "value 2"
    });
  }

结果是

{
    "name": "Name",
    "new_property": "value 2"
}

虽然这可能有效,但我强烈建议您不要对数据库实体和DTO使用相同的类。这可能会导致各种各样的问题;现在,ItemEntity同时表示两个不同的概念,一个是数据库中的实体,另一个是与外部世界的契约,模型中的任何更改都会反映在API中(反之亦然)。

相关问题