Class-transformer: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.

Created on 12 Apr 2017  路  16Comments  路  Source: typestack/class-transformer

Hello,

My code

public async findOne<T>(cls: ClassType<T>, query:any): Promise<T> {
    let collectionName = Reflect.getMetadata('collectionName', cls);
    let collection = this.mongo.collection(collectionName);
    let json: {} = await collection.findOne(query); // -> returns plain js object
    if(json === null) return null;
    return plainToClass(cls, json);
}

When i use this, it works just fine

    return deserialize(cls, JSON.stringify(json));

Error

TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.
    at fromObject (buffer.js:274:9)
    at Function.Buffer.from (buffer.js:106:10)
    at new Buffer (buffer.js:85:17)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:77:32)
    at _loop_1 (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:146:45)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:169:17)
    at _loop_1 (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:146:45)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:169:17)
    at /home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:26:41
    at Array.forEach (native)

Is this bug or am i doing something wrong.

Most helpful comment

I was having the same issue while working with Mongoose documents (don't even try without the .lean() option (or .toObject() when not a query), otherwise expect spectacular crashes).

Investigating a bit further, I found that even leaned objects have an _id property for which Object.keys returns [ '_bsontype', 'id' ], which causes the above error when class-transformer loops over those keys.

My curent solution is to assign doc.id = doc._id and then delete doc._id. Also make sure to have _id disabled for all your subdocuments, otherwise the same problem will occur.

All 16 comments

I think problem is in buffer.js file - new Buffer() requires argument. You can create Buffer object outside class-transformer and then use plainToClassFromExist function.

I was having the same issue while working with Mongoose documents (don't even try without the .lean() option (or .toObject() when not a query), otherwise expect spectacular crashes).

Investigating a bit further, I found that even leaned objects have an _id property for which Object.keys returns [ '_bsontype', 'id' ], which causes the above error when class-transformer loops over those keys.

My curent solution is to assign doc.id = doc._id and then delete doc._id. Also make sure to have _id disabled for all your subdocuments, otherwise the same problem will occur.

I had the same error message (also in a Mongoose context like @gempain )
But I already got rid of all _id properties for the main object and nested objects.
The problem is: I have a property which is a reference to another Mongoose document. Mongoose references also use object ids.

Is there a way class-transformer can handle MongoDB style object ids?

...using @Type(() => Mongoose.Types.ObjectId) for the reference property did not help...

Any update on how this can be solved?

I am using this: @Type(() => String)

Is there a solution or workaround for this problem now?

Since Buffer is such an integral part of Node.js I think it would be nice for the library to support it natively and without trickery. Since Buffer is a Node.js module there should be some check for it, but that should not be hard.

Like i have mentioned in the PR #221, I don't think this is a good idea.
Buffer is a node module (at least from my understanding, correct me if I'm wrong), that means that it would make this library incompatible for usage in web.

Otherwise a polyfill would be needed to execute it there.

If I missing something please correct me and i merge the PR ASAP

I have responded in the PR, but I will do too here. It's correct that it's a node.js specific module, but class-transformer becomes very hard to implement if a plain js object has a Buffer object as a property, since Buffer should be instantiated with Buffer.from() and not via new Buffer() which requires two arguments.
Buffer is a very integral part of node.js and is used in a variety of Node.js Packages, fx mysql, which is where I found the problem when parsing.
To work around the problem that it is a Node.js module I added a function to check for the Buffer module, and skip the instantiation if not present. This way it can work in both Node.js and browser environments.
Let me know what you think.

@MTschannett I have answered your comment. Please see if it makes sense.

Sorry for the late answer. I wanted to think about this, because I saw a few problems of this kind in the last few weeks (or at least I think they are of the same kind.

Is this really working in browser? Have you tested this? I mean it would be good ^^

I've thought about this for a bit and came up with a idea, which I'm not sure is practicable.

I thought about an API where you can register Types like Buffer and a factory method for it.

If you need Buffer you register it at the root of your project (e.g. main.ts in angular) and we check against it on every run.

If this works it would be a good idea for the long run. What do you think about this?

To fix your problem for now we can merge this PR.

Your thoughts about registering the types are also something I was thinking about. It would be a generic solution to the problem.

So about the test, is have tested it and I have even made a test for it, but I realized that the tests would not run in an environment that is not node.js, because of the Buffer transformation tests. So is it a requirement that the tests work in environments that are not node.js?

I can look into how to create a generic solution for custom types.

No that's not a requirment, they are like they are now. Thanks.

It would be great if you could look into the generic solution. But please open a new issue for that then

I will close this issue and create a follow up issue to discuss and implement the generic solution.

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