You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Mongoose至6.0.0后触发BSONTypeError: Decimal128参数错误

解决Mongoose 6升级后Decimal128转换的BSONTypeError问题

错误原因

Mongoose 6.x对BSON Decimal128类型的序列化/反序列化逻辑做了调整:

  • 5.x版本中,mongoose返回的文档默认会把Decimal128字段自动序列化为字符串;
  • 6.x版本则保留了Decimal128实例,而你的TransformDecimal128装饰器未适配这种变化,导致plainToClass处理时,要么装饰器错误地尝试用Decimal128实例创建新的Decimal128对象,要么class-transformer默认逻辑无法识别该实例,触发构造参数校验错误。

解决方案

1. 修复TransformDecimal128装饰器逻辑

确保装饰器能正确识别并转换mongoose 6的Decimal128实例,同时区分转换方向(数据库→DTO 或 DTO→数据库):

import { Transform } from 'class-transformer';
import { Decimal128 } from 'mongoose';

export function TransformDecimal128() {
  return Transform(({ value }) => {
    // 从数据库取出的Decimal128实例,转换为number(或字符串,避免精度丢失)
    if (value instanceof Decimal128) {
      // 若数值过大建议用toString()保留精度,转number可能丢失小数位
      return Number(value.toString());
    }
    // 从DTO传入的数值,转换为Decimal128用于存储
    if (typeof value === 'number' || typeof value === 'string') {
      return Decimal128.fromString(value.toString());
    }
    return value;
  });
}

2. 调整mongoose文档的序列化方式

在获取inputObject时,先将mongoose文档转换为普通JS对象,把Decimal128实例转为字符串,减少装饰器的处理压力:

// 假设receiptDoc是mongoose查询返回的文档对象
const inputObject = receiptDoc.toObject({ 
  getters: true, // 启用getters转换
  virtuals: false,
  transform: (doc, ret) => {
    // 手动处理Decimal128字段转字符串
    if (ret.sum instanceof Decimal128) {
      ret.sum = ret.sum.toString();
    }
    return ret;
  }
});
const result = plainToClass(GetReceiptDto, inputObject);

3. 确保class-transformer配置正确

调用plainToClass时启用隐式转换,确保装饰器逻辑被正确执行:

const result = plainToClass(GetReceiptDto, inputObject, {
  enableImplicitConversion: true,
  excludeExtraneousValues: true // 过滤DTO中未定义的字段
});

验证点

  • 检查GetReceiptDto中sum字段的类型是否为number(或string,若需保留高精度);
  • 测试从数据库查询数据后转换为DTO的流程,确认sum字段正常转换且无报错;
  • 测试前端传入数值后转换为Decimal128存入数据库的流程,确保数据一致性。

内容的提问来源于stack exchange,提问作者Sophie Jacquin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:37:15