class-transformer装饰器详解:@Expose与@Exclude的高级应用

class-transformer装饰器详解:@Expose与@Exclude的高级应用

【免费下载链接】class-transformer 【免费下载链接】class-transformer 项目地址: https://gitcode.com/gh_mirrors/cla/class-transformer

在TypeScript开发中,处理对象序列化(Serialization)和反序列化(Deserialization)时,我们经常需要控制哪些属性应该被包含或排除。class-transformer库提供了强大的装饰器(Decorator)机制来实现这一需求,其中最基础也最常用的就是@Expose@Exclude。本文将深入解析这两个装饰器的工作原理、高级用法及实际应用场景,帮助开发者在项目中灵活控制对象的属性可见性。

核心装饰器基础:@Expose与@Exclude的定义

@Expose@Exclude是class-transformer中用于控制属性暴露与排除的核心装饰器,定义于src/decorators/expose.decorator.tssrc/decorators/exclude.decorator.ts文件中。

@Expose装饰器

@Expose用于标记类或属性为“包含”状态,默认情况下会在序列化(classToPlain)反序列化(plainToClass) 两个方向生效。其核心实现逻辑如下:

export function Expose(options: ExposeOptions = {}): PropertyDecorator & ClassDecorator {
  return function (object: any, propertyName?: string | Symbol): void {
    defaultMetadataStorage.addExposeMetadata({
      target: object instanceof Function ? object : object.constructor,
      propertyName: propertyName as string,
      options,
    });
  };
}

通过options参数可限制其作用方向,例如:

  • toPlainOnly: true:仅在序列化(类实例→普通对象)时暴露
  • toClassOnly: true:仅在反序列化(普通对象→类实例)时暴露

@Exclude装饰器

@Exclude@Expose相反,用于标记类或属性为“排除”状态,默认同样作用于两个方向。其实现与@Expose类似:

export function Exclude(options: ExcludeOptions = {}): PropertyDecorator & ClassDecorator {
  return function (object: any, propertyName?: string | Symbol): void {
    defaultMetadataStorage.addExcludeMetadata({
      target: object instanceof Function ? object : object.constructor,
      propertyName: propertyName as string,
      options,
    });
  };
}

同样支持toPlainOnlytoClassOnly选项控制作用方向。

基础用法:属性级别的包含与排除

场景1:排除敏感属性

在用户信息类中,密码等敏感字段需要在序列化时排除。例如sample/sample2-iheritance/Album.ts中的实现:

export class Album {
  id: number;
  name: string;
  
  @Exclude() // 默认在序列化和反序列化时均排除
  private secretKey: string; // 敏感字段不参与转换
}

场景2:暴露只读计算属性

对于需要在序列化时暴露但无需反序列化的计算属性,可使用@Expose({ toPlainOnly: true })

export class User {
  firstName: string;
  lastName: string;
  
  @Expose({ toPlainOnly: true })
  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
}

高级应用:类级装饰与方向控制

类级@Exclude与属性级@Expose的组合

当整个类被标记为@Exclude时,默认会排除所有属性,此时可通过@Expose手动指定需要包含的属性:

@Exclude() // 类级排除:默认所有属性不参与转换
export class User {
  @Expose() // 显式暴露id
  id: number;
  
  @Expose({ toClassOnly: true }) // 仅反序列化时暴露
  password: string;
  
  // 未标记@Expose,默认被排除
  private internalCode: string;
}

方向控制示例

通过toPlainOnlytoClassOnly实现精细化控制:

export class User {
  @Expose({ toPlainOnly: true }) // 仅序列化暴露(对外展示)
  createdAt: Date;
  
  @Expose({ toClassOnly: true }) // 仅反序列化暴露(接收输入)
  password: string;
  
  @Exclude({ toPlainOnly: true }) // 序列化时排除(内部使用)
  lastLoginIp: string;
}

实战案例:继承场景下的装饰器应用

sample/sample2-iheritance/目录中,展示了继承场景下装饰器的使用。例如Album类继承自Authorable接口,并排除了特定属性:

import { Exclude } from '../../src/decorators';
import { Authorable } from './Authorable';

export class Album implements Authorable {
  id: number;
  name: string;
  authorId: number;
  
  @Exclude() // 排除内部管理字段
  _metadata: Record<string, any>;
}

转换效果验证

使用sample/sample1-simple-usage/app.ts中的转换逻辑验证效果:

// 序列化:类实例→普通对象
const userInstance = new User();
const plainObject = classToPlain(userInstance);
// plainObject中将不包含被@Exclude标记的属性

// 反序列化:普通对象→类实例
const jsonData = { id: '1', password: 'secret' };
const user = plainToClass(User, jsonData);
// user实例中仅包含@Expose或未被排除的属性

常见问题与解决方案

问题1:装饰器不生效

可能原因

  • 未启用TypeScript装饰器支持(需在tsconfig.json中配置experimentalDecorators: true
  • 转换时未使用class-transformer提供的plainToClassclassToPlain方法

解决方案

// 确保正确导入转换方法
import { plainToClass, classToPlain } from '../../src/index';

问题2:继承属性的排除规则

当父类和子类同时使用装饰器时,子类装饰器会覆盖父类规则。例如:

class Parent {
  @Exclude()
  id: number;
}

class Child extends Parent {
  @Expose() // 覆盖父类的@Exclude,使id属性暴露
  id: number;
}

总结与最佳实践

  1. 敏感字段必排除:用户密码、令牌等敏感信息必须用@Exclude排除
  2. 方向控制优先:优先使用toPlainOnly/toClassOnly明确作用方向
  3. 类级排除慎用:类级@Exclude会增加维护成本,建议优先使用属性级装饰器
  4. 继承场景注意覆盖规则:子类装饰器会覆盖父类同名属性的规则

通过合理组合@Expose@Exclude,可在前后端数据交互、日志输出、缓存存储等场景中灵活控制对象的属性可见性,提升代码安全性和数据处理效率。完整装饰器实现可参考src/decorators/目录源码,更多使用示例见test/functional/目录下的测试用例。

【免费下载链接】class-transformer 【免费下载链接】class-transformer 项目地址: https://gitcode.com/gh_mirrors/cla/class-transformer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值