Hello guys,
I created an endpoint with routing-controller, from @pleerock :
import { JsonController, Param, Get, NotFoundError } from "routing-controllers";
@JsonController("my-route")
export class MyController {
@Get("/:marketingId")
async getOne(@Param("marketingId") marketingId: string) {
let marketing: MarketingAutomation = await MyDB().findOne({
'_id': new ObjectId(marketingId)
});
console.log(marketing._id instanceOf ObjectId) // writes true
if (!!marketing && marketing._id) {
return classToPlain(marketing);
}
throw new NotFoundError(`User was not found.`);
}
}
The model, MarketingAutomation is:
import { ObjectId } from "mongodb";
import { IsDefined, IsString } from 'class-validator';
import { Expose } from 'class-transformer';
export class MarketingAutomation {
_id?: ObjectId;
companyId?: ObjectId;
@IsDefined()
@IsString()
name: string;
@Expose({name: '_id', toPlainOnly: true})
id() { return this._id.toHexString();}
@Expose({name: 'companyId', toPlainOnly: true})
_companyId() { return this.companyId.toHexString();}
}
The response is :
{
"_id": {
"_bsontype": "ObjectID",
"id": {"0":89,"1":186,"2":173,"3":122,"4":253,"5":210,"6":194,"7":101,"8":17,"9":9,"10":73,"11":26}
},
"name": "test",
"companyId": {
"_bsontype": "ObjectID",
"id": {"0":87,"1":63,"2":67,"3":251,"4":214,"5":195,"6":157,"7":16,"8":0,"9":72,"10":9,"11":211}
}
}
The response I would like to receive is:
{
"_id": "59baad7afdd2c2651109491a",
"name": "test",
"companyId": "rf41237afdd2c2651109gt45"
}
When you look at the response, you see that _id and companyId are not transformed in strings
Do you know how to achieve it ?
Thank you very much !
Can't reproduce this behavior, but I think you have name conflict. Try to add @Exclude to ObjectId properties:
@Exclude({toPlainOnly: true})
_id?: ObjectID;
@Exclude({toPlainOnly: true})
companyId?: ObjectID;
Do you really need these id and _companyId getters?
You can add @Transform decorator to existing properties instead:
@Transform((id: ObjectID) => id.toHexString(), {toPlainOnly: true})
_id?: ObjectID;
@Transform((id: ObjectID) => id.toHexString(), {toPlainOnly: true})
companyId?: ObjectID;
Thank @Petr0vi4, I tried it but it fails:
@Type(() => ObjectId)
@Transform(value => value.toHexString(), {toPlainOnly: true})
_id?: ObjectId;
```json
{
"name": "TypeError",
"message": "Cannot read property 'prototype' of undefined",
"stack": "TypeError: Cannot read property 'prototype' of undefined.../node_modules/class-transformer/metadata/MetadataStorage.js:131:84"
}
Do you know what happens ?
I found an alternative but it is not as clean:
```ts
let instance = plainToClass(classType, JSON.parse(JSON.stringify(plain)));
return classToPlain(instance);
I have the same issue. Looks like there is some implicit to string conversion. I found the following workaround:
@Expose()
public get id() {
return this._id ? this._id.toHexString() : undefined;
}
@Exclude()
// tslint:disable-next-line:variable-name
public _id?: ObjectId;
@VivienAdnot The reason for this is that when the JS engine transforms the object it calls the toJSON function recursively under the hood and ObjectId doesn't provide a custom implementation for it, so the default built-in will run what outputs the underlying object.
The proper solution is what @Petr0vi4 wrote in his second comment.
I will go ahead and close this, feel free to continue the discussion if you still have any question.
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.
Most helpful comment
I have the same issue. Looks like there is some implicit to string conversion. I found the following workaround: