Open replyqa opened 3 years ago
I know this issue is over three years old, but I was facing the same problem and I found a workaround. If anyone knows a better solution, let me know.
You can extend the ClassTransformOptions
interface to contain a context:
export interface ClassTransformOptionsWithContext extends ClassTransformOptions {
context?: unknown;
}
Then whenever a method asked for ClassTransformOptions
you can provide ClassTransformOptionsWithContext
:
export function serializeData<I>(instance: I, options?: ClassTransformOptionsWithContext): I {
return instanceToPlain(instance, {
excludeExtraneousValues: true, // <- example, set here your global TransformOptions
...(options ?? {}),
}) as I;
}
In a transformation you can do this:
export class ExampleClass {
@Transform(({obj, value, options}: {obj: any, value: number, options: ClassTransformOptionsWithContext}) => {
if(options?.context?.replaceNumber) {
return options.context.replaceNumber;
}
return value;
})
someNumber: number;
constructor(partial?: Partial<ExampleClass>){
if(partial) Object.assign(this, partial);
}
}
const serialized = serializeData(new ExampleClass({
someNumber: 123
}); // = {someNumber: 123};
const serialized2 = serializeData(new ExampleClass({
someNumber: 123
}, {context: { replaceNumber: -123 } }); // = {someNumber: -123};
For NestJS users: You can set a fixed by request context using @SerializeOptions()
or you can disable the serialization for the method and use my proposed serializeData() function and return its value. That would allow you to set a context dynamically.
Description
Sometimes, transformations require external values. For example, if you have a geopoint field in the class being converted, you can calculate the distance between that geopoint and the geopoint in the context (in nestjs that can be the requesting user's geopoint).
Proposed Solution
This can all be done manually, but if we are going to do this manually, then it defeats the purpose of using class-transformer, especially when used with arrays. Why not include an optional context in the transform options, and then pass it as an argument to the transform function?
The Django way
In Django, a serialization context can be passed that makes this extremely easy. Does class-transformer have such an option?