Class-transformer: classToPlain fails to transform TypeORM Mongo ObjectId to string

Created on 25 Apr 2018  路  5Comments  路  Source: typestack/class-transformer

Hi!

I'm facing similar issue which is presented in here, but the proposed solution is not working for me. I'm using routing-controllers to perform the routing, and with it's JSON method, it fails to serialise ObjectID into string, which is why I'm using class-transformer.

However, when I'm trying to convert the ObjectID to a string in a way proposed in the earlier issue I mentioned. I get the following error:

TypeError: id.toHexString is not a function
    at TransformMetadata.class_transformer_1.Transform [as transformFn] (/Users/max/Projects/backend-boilerplate/src/entity/User.js:18:46)
    at /Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:211:30
    at Array.forEach (<anonymous>)
    at TransformOperationExecutor.applyCustomTransformations (/Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:210:19)
    at _loop_1 (/Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:155:41)
    at TransformOperationExecutor.transform (/Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:178:17)
    at /Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:33:41
    at Array.forEach (<anonymous>)
    at TransformOperationExecutor.transform (/Users/max/Projects/backend-boilerplate/node_modules/class-transformer/TransformOperationExecutor.js:30:19)
    at ClassTransformer.classToPlain (/Users/max/Projects/backend-boilerplate/node_modules/class-transformer/ClassTransformer.js:9:25)

Without class-transformer, the JSON output looks like this

[
    {
        "id": {
            "_bsontype": "ObjectID",
            "id": {
                "0": 90,
                "1": 224,
                "2": 40,
                "3": 220,
                "4": 11,
                "5": 86,
                "6": 132,
                "7": 6,
                "8": 66,
                "9": 66,
                "10": 231,
                "11": 130
            }
        },
        "username": "test"
    },
   ...
]

I suspect this is issue where class-transformer fails to cast id as a Mongo ObjectId, because if I try to perform toHexString-function in the controller before it gets passed further, everything runs smoothly.

I'd however like to keep database level stuff in the model away from controller, which I see more like of more abstract layer: place for business logic.

See the code I'm using to reproduce and debug this issue more conveniently: https://bitbucket.org/vertics/typescript-typeorm-mongo-boilerplate/src

Most helpful comment

I tried resolving this from the class-transformer repo code, but experimental features in TS were too much for me.

I copied a ObjectID toHexString implementation from BSON repo for my code that can be used in Transform

toHexString.ts

export default function(value) {
  const hexTable = []
  for (let i = 0; i < 256; i++) {
    hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16)
  }

  const id = Object.keys(value.id).map(key => value.id[key])

  let hexString = ''
  for (const el of id) {
    hexString += hexTable[el]
  }
  return hexString
}

which can be then used in elsewhere like this

entity/User.ts

import {Transform} from 'class-transformer'
import {Column, Entity, ObjectID, ObjectIdColumn} from 'typeorm'
import toHexString from './../toHexString'

@Entity()
export class User {

  @ObjectIdColumn()
  @Transform(toHexString, {toPlainOnly: true})
  public id: ObjectID

  @Column()
  public username: string
}

All 5 comments

I tried resolving this from the class-transformer repo code, but experimental features in TS were too much for me.

I copied a ObjectID toHexString implementation from BSON repo for my code that can be used in Transform

toHexString.ts

export default function(value) {
  const hexTable = []
  for (let i = 0; i < 256; i++) {
    hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16)
  }

  const id = Object.keys(value.id).map(key => value.id[key])

  let hexString = ''
  for (const el of id) {
    hexString += hexTable[el]
  }
  return hexString
}

which can be then used in elsewhere like this

entity/User.ts

import {Transform} from 'class-transformer'
import {Column, Entity, ObjectID, ObjectIdColumn} from 'typeorm'
import toHexString from './../toHexString'

@Entity()
export class User {

  @ObjectIdColumn()
  @Transform(toHexString, {toPlainOnly: true})
  public id: ObjectID

  @Column()
  public username: string
}

@Transform or @Type can help with this problem, but what if I can't use them? For example, if I have mongodb document without mapping. Can targetMaps in ClassTransformOptions help with that? I tried, but no luck

Using Transform is the right solution. I am closing this, as I see you have solved your issue.

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

Related issues

ERPedersen picture ERPedersen  路  4Comments

VivienAdnot picture VivienAdnot  路  6Comments

prbaron picture prbaron  路  3Comments

ceopaludetto picture ceopaludetto  路  3Comments

NathanHazout picture NathanHazout  路  5Comments