答复:
我已经对整个系统进行了分析和调试
TransformOperationExecutor.ts
,简单地说,没有内置的方法来抑制这个执行者试图进行的无数转换。我在想也许可以移除
@Type
所有的装饰师都能达到这个目标。但即使缺少类型信息,该库仍会尽可能地将复杂对象转换为普通对象。原因是什么
@Transform(({value})=>...)
不起作用的是,即使对于返回的值,也会有多个检查来确定转换后的值是否需要进一步转换。”
平原
".
解决方法:
我看到的唯一解决方案是自己构建该功能。我可以提供以下实现来模拟
@Ignore
特点:
import { classToPlain, ClassTransformOptions, Transform, TransformFnParams } from 'class-transformer';
// New decorator to be used on members that should not be transformed.
export function Ignore() {
// reuse transform decorator
return Transform((params: TransformFnParams) => {
if (params.type == TransformationType.CLASS_TO_PLAIN) {
// class-transformer won't touch functions,
// so we use function-objects as container to skip transformation.
const container = () => params.value;
container.type = '__skipTransformContainer__';
return container;
}
// On other transformations just return the value.
return params.value;
});
}
// Extended classToPlain to unwrap the container objects
export function customClassToPlain<T>(object: T, options?: ClassTransformOptions) {
const result = classToPlain(object, options);
unwrapSkipTransformContainers(result);
return result;
}
// Recursive function to iterate over all keys of an object and its nested objects.
function unwrapSkipTransformContainers(obj: any) {
for (const i in obj) {
if (obj.hasOwnProperty(i)) {
const currentValue = obj[i];
if (currentValue?.type === '__skipTransformContainer__') {
// retrieve the original value and also set it.
obj[i] = currentValue();
continue;
}
// recursion + recursion anchor
if (typeof currentValue === 'object') {
unwrapSkipTransformContainers(currentValue);
}
}
}
}
该解决方案利用了类转换器不会转换函数(get/set函数除外),因为这些函数不是普通对象的一部分。我们重复使用
Transform
decorator来包装我们不想被函数转换的成员。我们还用字符串标记这些函数
__skipTransformContainer__
以便以后很容易找到它们,并且不会意外地调用错误的函数。然后我们写一个新的
customClassToPlain
,它首先调用默认值
classToPlain
然后对结果调用递归展开函数。展开函数被调用
unwrapSkipTransformContainer
并递归搜索所有
__skipTransformContainer__
-容器来检索未转换的值。
用法:
export abstract class StopStep extends Step {
id: string;
name: string;
description: string;
pointOfInterest: PointOfInterest | null;
address: string;
@Ignore()
coordinates: firebase.firestore.GeoPoint;
}
class ExampleStep extends StopStep {/*logic*/}
const step = new ExampleStep();
const plain = customClassToPlain(step);