class-transformer icon indicating copy to clipboard operation
class-transformer copied to clipboard

feature: Expose JS object(Record) should work when strategy='excludeAll'

Open Nikolay-Uvarov opened this issue 4 years ago • 1 comments

Description

We use default strategy excludeAll and created the following class:

export class Data { @Expose() @IsOptional() public metadata?: Record<string, unknown>; }

But after transformation we got metadata field is empty object. All metadata field keys are removed in getKeys method. It will be great if there are all fields from metadata property after transformation. We found workaround but we think it is not good enough.

export class DownloadData { @Expose() @IsOptional() @Transform((value) => value.obj?.metadata) public metadata?: Record<string, unknown>; }

Proposed solution

For example, add to @Expose() a property { strategy: 'exposeAll' }. (@Expose('exposeAll' )).

Thanks in advance.

Nikolay-Uvarov avatar Apr 28 '21 21:04 Nikolay-Uvarov

@Nikolay-Uvarov This worked for me with deeply nestd objects:

export class Data {
  @Expose()
  @IsOptional()
  @Transform(transfromExposeAll())
  public metadata?: Record<string, unknown>;
}
/** Exposes all nested objects when strategy is set to `excludeAll` */
export const transfromExposeAll = () => {
  @Expose()
  class ExposeAll {}

  @Expose()
  class ExposeAllMap extends Map<unknown, unknown> {}

  @Expose()
  class ExposeAllSet extends Set<unknown> {}

  const transform = (source: unknown): unknown => {
    if (Array.isArray(source)) {
      return source.map(transform);
    } else if (source instanceof Set) {
      return new ExposeAllSet(Array.from(source).map(transform));
    } else if (source instanceof Map) {
      return new ExposeAllMap(Array.from(source.entries()).map(([key, value]) => [key, transform(value)]));
    } else if (typeof source === "object" && source !== null) {
      return Object.assign(
        new ExposeAll(),
        Object.fromEntries(Object.entries(source).map(([key, value]) => [key, transform(value)])),
      );
    } else {
      return source;
    }
  };

  return ({ key, obj }: Pick<TransformFnParams, "key" | "obj">) => transform((obj as Record<string, unknown>)[key]);
};

aravindanve avatar Dec 23 '24 11:12 aravindanve