Skip to content
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

feat: allow to ignore unset properties during classToPlain transformation #35

Closed
hepiyellow opened this issue Dec 8, 2016 · 21 comments
Closed
Labels
status: done/released Issue has been completed, no further action is needed. type: feature Issues related to new features.

Comments

@hepiyellow
Copy link

I would expect a property which is undefined in the Class to not appear at all in the Plain object representation.

Or at least to have a flag to control this.

Is there any workaround?

@petersondrew
Copy link

Same question here, this seems counter-intuitive, or at least should be controlled by a transformation option.

@NoNameProvided NoNameProvided added the type: question Questions about the usage of the library. label Oct 26, 2018
@NoNameProvided
Copy link
Member

The property is on your class or is it only in the plain object?

If it's in the class, this is the expected behavior, class-transformer doesn't assume anything about having undefined or null in a property and will just copy it over.

If you class doesn't include them then you can use a @Exclude/@Expose to handle this:

@Exclude() // removes all properties from output
class Example {
 	
  @Expose() // manually expose this
  name: string;

  @Expose() // manually expose this
  email: string
}

I will go ahead and close this if you have any further question please continue the discussion here.

@kalani96746
Copy link

@NoNameProvided Hi, I have the same concern, could you reopen this issue. I am doing transformation to an api (plain object). in typescript I define the properties (they are optional). However when running classToPlain these can get null or undefined as they were never set (its possible they do get set though). The problem is the remote API interprets the existence of the property as an instruction that it was setting...and it doesnʻt like the fact that phoneNumber doesnʻt match its own validation rules since it is null and not a actual phone number. It wouldnʻt have given the error if it were not present on the object since the Remote API defines these fields as optional.

can you run something like this on the transformed object as a transformation option for classToPlain?

function clean(obj) {
var propNames = Object.getOwnPropertyNames(obj);
for (var i = 0; i < propNames.length; i++) {
var propName = propNames[i];
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName];
}
}
}

@NoNameProvided NoNameProvided reopened this May 9, 2019
@dannyhuly
Copy link

@NoNameProvided Hi,

I'm having the same issue where I'm unable to ignore/exclude properties that are undefined

In the following example https://codesandbox.io/s/angular-hgjdc in trying to exclude the optinalFilter prop only if its undefined.

Hope this helps solidify the issue.

@kalani96746
Copy link

So this is actually causing quite the issue for us in firebase...since firebase chokes on any property that is there and is equal to undefined. So there is a difference between a property that exists and whos value who is set to is undefined and a property which just does not exist

object["foo"] = undefined; //assigns undefined to object.foo (will appear in chrome console)

this is the only real way to delete a property.
delete object["foo"]; //stops appearing in chrome console.

note undefined == null (true) but undefined === null (false)

Can we ad something to delete if object["foo"] === undefined

@kalani96746
Copy link

I think I found the link but have been struggling with local node packages (unable to use npm link w/node modules) when using with angular so I havenʻt been able to test this out.

Approx line 253 of TransformOperationExecutor.ts
I think the following will fix the issue.
if(finalValue !== undefined) {
newValue[newValueKey] = finalValue;
}

added the undefined check so it wouldnʻt create a property (i.e. key present in Object.keys()) with a value === to undefined. (i.e. define an undefined property...present in chrome console). This causes issues with Firebase's firestore and firebase refuses to save the plainObject because of the undefined properties. Iʻve been having to take the plainObject output and JSON.parse(JSON.stringify(plainObject)) to get past the issue but it has a performance cost.

@joeybenenati
Copy link

joeybenenati commented Sep 26, 2019

I'm getting caught on this too. It would be nice if @expose took a conditional function, or there was an @ExposeIf decorator

@ruscon
Copy link
Contributor

ruscon commented Sep 26, 2019

@NoNameProvided, so this is a bug or expected behavior?

if it is the bug, can we implement @kalani96746's solution?

@Michael-Dawkins
Copy link

It would be helpful if transformations took an argument to specify this behavior, like so:
classToPlain(myObjects, { groups: ['user'], excludeExtraneousValues: true, ignoreUndefined: true })

class-tranformer is ideal for making clean DTOs but currently I have to delete undefined values manually before sending the data down through the pipe

@nolazybits
Copy link

nolazybits commented Nov 24, 2019

@NoNameProvided , this is becoming a problem with the latest typescript 3.7
All property will always be initialized to undefined if they don't have an initializer

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier

There are workaround, but it would be nice to maybe revisit this.

@molinab297-unisys
Copy link

I have a need for this as well....

@MarshalX
Copy link

MarshalX commented Jul 1, 2020

I have a need for this as well....

Does this solve your need: JSON.parse(classTransformer.serialize(object));?

@AndreasDvrs
Copy link

AndreasDvrs commented Dec 9, 2020

Hi, I need this as well. Problem is it conflicts with class-validator @IsNotEmptyObject decorator.
In my case (nestJS), we expect receive an object like: person: { hair: "black", age: 43 }

In case we receive: person: {}
@IsNotEmptyObject should be triggered.

Now in order to validate this we need to turn it into a class instance using plainToClass. The problem is that after plainToClass completes we have:
person: { hair: undefined, age: undefined }
So the class-validator validate method does not trigger @IsNotEmptyObject

Update: We ended up creating a custom validation decorator since class-validator provides this (really great) option.

@cerireyhan
Copy link

cerireyhan commented Feb 13, 2021

This looks like a still valid issue in 2021. Is there any progress on it? At least it could be provided as a simple boolean option and used with solution provided above by @kalani96746. In fact, this would also be useful in plainToClass transformation as well.

@NoNameProvided NoNameProvided added type: feature Issues related to new features. and removed type: question Questions about the usage of the library. labels Feb 14, 2021
@NoNameProvided NoNameProvided changed the title classToPlain creates undefined properties feat: allow to ignore unset properties during classToPlain transformation Feb 14, 2021
@NoNameProvided
Copy link
Member

Added in 2356b3a. Will be included in the next release.

@NoNameProvided NoNameProvided added the status: fixed Issues with merged PRs, but not released yet label Feb 14, 2021
@NoNameProvided NoNameProvided added status: done/released Issue has been completed, no further action is needed. and removed status: fixed Issues with merged PRs, but not released yet labels Feb 14, 2021
@NoNameProvided
Copy link
Member

Released as 0.4.0.

@cerireyhan
Copy link

@NoNameProvided Thanks for the fast reply! Version 0.4.0 works perfect. Just wanted to point out one mistake in the comments of ClassTransformOptions interface.

  • When set to true undefined fields will be ignored during class to plain transformation.

The comment is wrong since it should be set to false to ignore the undefined fields. And this works in both plainToClass & classToPlain transformations not just classToPlain. I know it's not the biggest issue but might cause confusion for those who are new to the lib :)

@NoNameProvided
Copy link
Member

Thanks for the fast reply!

This is a 4 years old ticket 😄 but thanks for the encouraging words!

The comment is wrong since it should be set to false to ignore the undefined fields.

Corrected.

And this works in both plainToClass & classToPlain transformations not just classToPlain.

Dang, that is an issue, I wanted to make it work for classToPlain only because I think a class should always have its declared properties set.

@dadashi
Copy link

dadashi commented Feb 14, 2021

I'd prefer it to be left as is. One can simply omit the option if they don't want it for plainToClass

@cerireyhan
Copy link

Dang, that is an issue, I wanted to make it work for classToPlain only because I think a class should always have its declared properties set.

Agreed.

I'd prefer it to be left as is. One can simply omit the option if they don't want it for plainToClass

Also, true since it has to be explicitly enabled.

@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: done/released Issue has been completed, no further action is needed. type: feature Issues related to new features.
Development

No branches or pull requests