Include @IsOptional values to the body if they are missing with default value
AndonMitev opened this issue · 3 comments
Having following DTO:
export class UserLoginRequestDto {
@IsOptional()
email: string;
@IsOptional()
password: string;
}
and passing outside body: { email: 'test@gmail.com' }
, how to create pipe that will check keys which are missing from the dto and assign to them null so after pipe, body becomes:
body: { email: 'test@gmail.com', password: null }
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { instanceToPlain, plainToClass } from 'class-transformer';
@Injectable()
export class AugmentOptionalPropertiesPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
const { metatype } = metadata;
if (!metatype) {
return value;
}
// Convert the incoming value to an instance of the DTO
const dtoInstance = plainToClass(metatype, value);
// Convert the DTO instance back to a plain object
const plainObj = instanceToPlain(dtoInstance, { excludeExtraneousValues: false });
// Assign null to undefined properties
for (const prop in plainObj) {
if (plainObj[prop] === undefined) {
plainObj[prop] = null;
}
}
console.log(Object.entries(metatype.prototype));
Object.entries(metatype.prototype).forEach(([key, defaultValue]) => {
if (dtoInstance[key] === undefined) {
dtoInstance[key] = null; // Or use 'defaultValue' if you want a specific default value
}
});
console.log('plainObj', plainObj);
return plainObj;
}
}
However i'm not able to find easy way to iterate over the keys from the DTO model it self, any ideas
The IsOptional
decorator is not a class-transformer
decorator so it will not have affect on the transformer.
I think you can use a custom Transformer to make this behavior using class-transformer
:
export class UserLoginRequestDto {
@Expose()
@Transform(({value}) => value ?? null )
email?: string;
@Expose()
@Transform(({value}) => value ?? null )
password?: string;
}
I have added the ?: to the types so typescript will know that it might be undefined (this is just a type, will not have affect, but in strict ts it will work nicely)
Also I have added a custom transformer to return null on undefined. Since the Transform only run when Exposed explicitly I have added the @Expose
as well. (you can create your very on @NullOnPlainTransform
decorator if you want to make it read nicely)
This is a way you can make this work using class-transformer
.
The thing you tried to implement I think can work a bit better since, you do not have to add anything on your existing DTO-s.
Just a note that you could use Object.getOwnPropertyNames as well to get the available keys and if it does not exists on your plain you can just set it to null.
This is a bit old question, so I assume you were already be able to make it work.
Closing as answered. If you have any questions left feel free to comment on this issue.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.