如何防止对象赋值、JSON反序列化时丢失类装饰器及元数据?
核心问题场景
问题1:对象字面量冒充类实例丢失元信息
直接用普通对象字面量创建类类型的变量时,不会走类的构造函数逻辑,也不会保留类上挂载的装饰器、原型方法等元信息,示例代码:
@jsonReflect() class TestClass { name?: string; age?: number; @jsonIgnore() address?: string; } // 该写法生成的是普通Object,不是TestClass的实例 const test = { name : "John", age: 10 };
问题2:JSON.parse反序列化结果丢失类元信息
JSON.parse的返回值永远是原生普通JavaScript对象,哪怕给它加上TypeScript类型标注,运行时也不会自动转换为对应类的实例,类上的装饰器规则、构造逻辑、元数据会完全丢失,导致后续序列化不符合预期,示例代码:
export class ConnectorSignature { name!: string; dataType!: string; @jsonIgnore() dataReference!: number; } // 仅为编译时类型标注,运行时connectorData是普通对象 const connectorData: ConnectorSignature = JSON.parse('{"name":"Blue","dataType":"Integer","dataReference":2}'); // 序列化时@jsonIgnore规则完全失效,会输出所有字段 console.log(JSON.stringify(connectorData)); // 输出结果:{"name":"Blue","dataType":"Integer","dataReference":2}
注意:TypeScript的类型标注仅在编译阶段生效,运行时会被完全擦除,不存在任何类型转换逻辑,直接给普通对象加类类型标注本质是类型欺骗,不会改变对象的实际运行时结构。
解决方案
阻止对象字面量冒充类实例
- 给类增加独有的私有标识字段,从TypeScript编译层面拦截非法赋值:
@jsonReflect() class TestClass { // 私有字段是类独有的,普通对象字面量不可能自带该字段 readonly #_brand = 'TestClass' as const; name?: string; age?: number; @jsonIgnore() address?: string; } // 此时TS会直接报类型错误,不允许将普通对象赋值给TestClass类型变量 const test: TestClass = { name : "John", age: 10 }; - 配置ESLint校验规则,开启
@typescript-eslint/no-unsafe-assignment、@typescript-eslint/no-explicit-any等规则,禁止无转换的普通对象到类类型的直接赋值,在代码检查阶段拦截不规范写法。
解决反序列化元信息丢失问题
- 禁止直接将
JSON.parse的返回值断言为类类型,所有类实例的反序列化必须走显式实例化逻辑:解析完JSON普通对象后,手动new出对应类的实例,再将字段逐一赋值到实例上,确保生成的是真正的类实例,示例:function parseConnectorSignature(jsonStr: string): ConnectorSignature { const raw = JSON.parse(jsonStr); const instance = new ConnectorSignature(); instance.name = raw.name; instance.dataType = raw.dataType; instance.dataReference = raw.dataReference; return instance; } const connectorData = parseConnectorSignature('{"name":"Blue","dataType":"Integer","dataReference":2}'); // 此时connectorData是真正的ConnectorSignature实例,装饰器规则可以正常生效 console.log(connectorData instanceof ConnectorSignature); // true - 项目中类序列化/反序列化场景较多时,统一使用支持装饰器规则的序列化工具类接管所有JSON转换逻辑,替换原生
JSON.parse和JSON.stringify:工具会自动识别类上的装饰器配置,反序列化时自动生成对应类的合法实例,序列化时自动跳过标记为忽略的字段,无需手动编写每个类的转换逻辑。 - 增加运行时校验:所有反序列化生成的实例,在使用前通过
instanceof做类型校验,拦截漏走转换逻辑的异常数据。
内容的提问来源于stack exchange,提问作者Azureus Aeterna
相关产品推荐
相关产品推荐

