-
Notifications
You must be signed in to change notification settings - Fork 512
fix: toClassOnly still expose the name in instanceToPlain #1324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Having this same problem. Is this only happening in newer versions? Is there a version to rollback to that this still works? |
Any updates on this? Still seems to be an issue. Is there a consensus on any workarounds for the time being? |
This seems to be a bug and needs fix. Until it is fixed, you could create another getter for toPlainOnly and exclude the current on toPlainOnly. If I am correct it should work, but I will write an example workaround later. |
For a quick (but not nice) fix you could do export class CreateEventDto {
@Expose()
@Exclude( { toPlainOnly: true })
type: number;
@Expose()
get eventTypeId() {
return this.type;
}
} |
@diffy0712 Thanks for the response and the temporary workaround. This will unfortunately be too verbose as I have a ton of exposed properties currently that are My Temporary SolutionNot sure if its relevant or if this is a correct solution but for my situation, I am using
import {
ClassSerializerContextOptions,
ClassSerializerInterceptor,
NestInterceptor,
PlainLiteralObject,
} from '@nestjs/common';
import { defaultMetadataStorage } from 'class-transformer/cjs/storage.js';
import type { MetadataStorage } from 'class-transformer/types/MetadataStorage';
/**
* This serializer is being used to fix an issue with the class-transformer library where
* instanceToPlain is not abiding by certain expose flags. This aims to remedy incorrectly keyed properties
* when specified as toClassOnly.
*
* Once the issue is resolved in the package, this should be able to be removed.
* @see https://github.com/typestack/class-transformer/issues/1324
*/
export class AppClassSerializerInterceptor
extends ClassSerializerInterceptor
implements NestInterceptor
{
/** Load in the default local storage... I realize this isn't supposed to be public and used */
private readonly metadata: MetadataStorage = defaultMetadataStorage;
override transformToPlain(
plainOrClass: any,
options: ClassSerializerContextOptions,
): PlainLiteralObject {
// Perform normal transform. This will have incorrect keys as it will have ignored the toClassOnly
const result = super.transformToPlain(plainOrClass, options);
// Recursively fix the result object and nested class objects
this.fixExposedKeys(plainOrClass, result);
return result;
}
/**
* Traverse the resulting object and compare it with class instance version. Patch the result model recursively
* checking nested objects.
*/
private fixExposedKeys(plainOrClass: any, result: PlainLiteralObject) {
// Get all the fields that are exposed and their options for the target class
const exposed = this.metadata.getExposedMetadatas(plainOrClass.constructor);
const toRevert = new Map<string, string>();
// Cache this classes exposed properties to lookup
for (const field of exposed) {
if (
field.options.toClassOnly &&
field.options.name &&
field.propertyName
) {
toRevert.set(field.options.name, field.propertyName);
}
}
for (const key in result) {
const val = result[key];
const correctKey = toRevert.get(key) ?? key;
// Convert the keys back to the originals and delete the incorrectly converted ones.
if (correctKey !== key) {
result[correctKey] = val;
delete result[key];
}
// We need to also fix nested models...
if (val && typeof val === 'object') {
this.fixExposedKeys(plainOrClass[correctKey], val);
}
}
}
} |
Thank you for sharing your solution. |
I have a DTO class and I want some specific key to be covert with different name only in instanceToPlain operation
the dto class:
I can get it to work in plainToInstance
for example:
but if I convert it again using instanceToPlain, the result is showing { type: 2 } instead of { eventTypeId: 2 }
Is there anything I'm doing wrong? or any proper way to this kind of conversion?
Thanks for answering :)
The text was updated successfully, but these errors were encountered: