Hello,
I was attempting to use this library to map DB values to a class (plainToClass). However, it's not supporting other objects such as a BSON ObjectID. I think it doesn't support ObjectID because of this line here:
https://github.com/mongodb/js-bson/blob/1.0-branch/lib/bson/objectid.js#L55
So I have two questions regarding this.
I have this Mongo doc:
{
_id: ObjectId('...'),
foo: 'bar',
createdAt: Date
}
and class:
class Example {
id: ObjectId;
foo: string;
createdAt: Date;
}
Thanks!
Have you seen TypeORM? It's exactly what you are looking for.
Ooops, I thought I replied to this. I have seen TypeORM. We're using MongoDB at the moment, and their current implementation of MongoDB is using an old driver and their issues keep growing on the Mongo side. Plus in most of our situations, we don't need a heavy object mapper like TypeORM. Mongo has a built-in "map" function on their cursor.
class User {
id: ObjectId;
username: string;
pass: string;
}
const users = await userCollection
.find()
.map((doc) => plainToClass(User, doc))
.toArray();
I was planning on the repository layer doing mapping for any class and using class-transformer to aid in it.
One issue I ran into is that the mapper, when running into ObjectId, internally tries to create a Buffer and errors out. (my 1. issue above)
I guess this is because we call this object with an invalid constructor.
We don't support to overgive a value (because no info is given at runtime about what information is needed). So the id is set to undefined, which is not checked by them a exception is thrown.
I think is the same as this #174.
Maybe you could work around this by using the @Transform-decorator
@j If you don't need this anymore, please close this issue.
@MTschannett is right you can work around your issue via using the @Transform and the @Expose operator.
class Example {
@Expose({ name: '_id' })
@Transform((objectId) => objectId.str, { toClassOnly: false })
id: string;
foo: string;
createdAt: Date;
}
A complete dummy example:
import { Expose, Transform, classToPlain, plainToClass } from 'class-transformer';
class Example {
@Expose({ name: '_id' })
@Transform((objectId) => objectId.str, { toClassOnly: false })
id: string;
foo: string;
createdAt: Date;
}
const classInstance = plainToClass(Example, {
_id: { x: 5, str: 'xxxxx' },
foo: 'yyyyy',
createdAt: new Date(),
});
console.log(classInstance); // Example聽{id: "xxxxx", foo: "yyyyy", createdAt: ...}
console.log(classInstance instanceof Example); // true
I will go ahead and close this, if you have any question please continue the discussion
If you are using NestJs with mongoose, you can simply do:
Schema File
export const ExampleSchema = new Schema({
foo: String,
createdAt: Date
});
Interface
export interface Example extends Document {
id: string; // NOTE: This field will be automatically mapped by the framework
foo: string;
createdAt: Date;
}
Dto Class
export class ExampleDto {
@Expose()
id: string;
@Expose()
foo: string;
@Expose()
createdAt: Date;
}
Controller
import { plainToClass } from 'class-transformer';
...
@Get()
async getExample() {
const result = await this.service.getExample();
return plainToClass(
ExampleDto, result, { strategy: 'excludeAll', enableImplicitConversion: true } // enableImplicitConversion is the magic, otherwise mongodb Id will be incorrectly converted
);
}
Enjoy guys
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
If you are using NestJs with mongoose, you can simply do:
Schema File
Interface
Dto Class
Controller
Enjoy guys