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

升级NestJS 10至11后JSON对象解析异常问题排查与修复

问题背景与现象

我有一个NestJS应用,包含如下POST端点:

@Post()
@HttpCode(HttpStatus.CREATED)
public async create(@Body() model: SerializedModel, @Req() req): Promise<SomeDto> {
    const sessionId = await this.modelStorage.add(await this.parseRequest(model, req));
    return {id: sessionId};
}

SerializedModel是带有自定义属性的JSON对象:

export const RootObjectMidPropertyKey = "rootObjectMID";

export class SerializedModel {
    [key: string]: any;

    public [RootObjectMidPropertyKey]: string;
}

SerializedModel的示例数据:

{
  "rootObjectMID": "W39MCbKB-session",
  "W39MCbKB-session": {
    "_mid": "W39MCbKB-session",
    "code": "W39MCbKB",
    "locale": "en-IE",
    "urlParameters": "?locale=en-IE",
    "unstructuredState": "unstructured-45353-3-34538134"
  }
}

在遍历SerializedModel实例的entries时出现异常:

Object.entries(serializedModel).forEach(([modelKey, modelValue]) => {
    stringifiedModel[modelKey] = JSON.stringify(modelValue);
});

打印结果显示键值对被逐个字符拆分:

modelKey:  0
modelValue:  {
modelKey:  1
modelValue:  
modelKey:  2
modelValue:  
modelKey:  3
modelValue:   
modelKey:  4
modelValue:   
modelKey:  5
modelValue:  "
modelKey:  6
modelValue:  r
modelKey:  7
modelValue:  o
modelKey:  8
modelValue:  o
modelKey:  9
modelValue:  t
modelKey:  10
modelValue:  O

而非预期的正常键值对:

modelKey:  rootObjectMID
modelValue:  W39MCbKB-session

代码逻辑未改动,请问NestJS新版本在JSON处理上有何默认行为变更?该如何修复?


原因分析(NestJS版本变更)

NestJS从v9升级到v10后,默认的JSON解析器从body-parser切换为@nestjs/platform-express内置的基于express.json()的解析器,且默认配置中开启了strict: true。这个配置会导致当传入的JSON无法被正确序列化为指定的类(SerializedModel)时,解析器会将其转换为字符串而非JSON对象。

你的SerializedModel使用了索引签名,但NestJS的ClassValidator/ClassTransformer在处理这类动态属性时,若未正确配置,会导致解析后的实例并非预期的JSON对象,而是被当作字符串处理,最终Object.entries遍历的是字符串的字符序列。


修复方案

有两种可行的修复方式:

方式一:修改JSON解析器配置

在main.ts中显式配置express的JSON解析器,关闭strict模式:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { json } from 'express';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 覆盖默认JSON解析配置,关闭strict模式
  app.use(json({ strict: false }));
  await app.listen(3000);
}
bootstrap();

方式二:调整SerializedModel的转换配置

使用class-transformer的装饰器,明确允许动态属性,并确保解析时正确转换:

import { Transform } from 'class-transformer';

export const RootObjectMidPropertyKey = "rootObjectMID";

export class SerializedModel {
    [key: string]: any;

    public [RootObjectMidPropertyKey]: string;

    // 自定义转换逻辑,确保动态属性被正确解析
    @Transform(({ value, obj }) => {
        return obj;
    })
    get dynamicProperties(): Record<string, any> {
        const result = { ...this };
        delete result[RootObjectMidPropertyKey];
        return result;
    }
}

同时在main.ts中确保开启了enableImplicitConversion:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({
    enableImplicitConversion: true,
    transform: true,
  }));
  await app.listen(3000);
}
bootstrap();

验证修复

修改后,Object.entries(serializedModel)将正确遍历JSON对象的键值对,而非字符串的字符。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:03:28