Class-transformer: feat: allow to ignore unset properties during `classToPlain` transformation

Created on 8 Dec 2016  路  21Comments  路  Source: typestack/class-transformer

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?

donreleased feature

Most helpful comment

Released as 0.4.0.

All 21 comments

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

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.

@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 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.

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

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.

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

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

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

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

@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.

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

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

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

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.

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.

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

Released as 0.4.0.

@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 :)

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.

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

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.

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.

Was this page helpful?
0 / 5 - 0 ratings