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

如何在NestJS中将Prisma结果转为自定义模型返回?支持全局配置吗?

在NestJS中全局统一响应格式(适配Prisma查询结果)

针对你需要将Prisma查询结果统一包装成指定响应结构的需求,NestJS提供了全局拦截器的方案,能一次性解决所有接口的响应格式统一问题,无需在每个接口中手动处理。

一、创建全局响应拦截器

拦截器是NestJS处理请求/响应生命周期的核心组件,正好用来统一包装返回结果。

  1. 新建拦截器文件 src/common/interceptors/transform.interceptor.ts:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Reflector } from '@nestjs/core';

// 自定义装饰器:用于设置接口的响应消息
export const ResponseMessage = (message: string) => Reflector.createDecorator<string>({
  key: 'responseMessage',
});

@Injectable()
export class TransformInterceptor implements NestInterceptor {
  constructor(private reflector: Reflector) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // 默认响应消息
    const defaultMsg = '操作成功';
    // 从控制器方法上获取自定义消息
    const message = this.reflector.get<string>('responseMessage', context.getHandler()) || defaultMsg;
    // 获取当前响应状态码
    const statusCode = context.switchToHttp().getResponse().statusCode;

    return next.handle().pipe(
      map(data => {
        // 统一包装成目标响应结构
        return {
          status: statusCode,
          message,
          data: {
            // 根据返回数据类型自动适配字段:单条数据用user,列表用list,可按需调整
            [typeof data === 'object' && !Array.isArray(data) ? 'user' : 'list']: data
          }
        };
      }),
    );
  }
}

二、全局注册拦截器

有两种方式将拦截器全局生效:

方式1:在AppModule中注册

修改 src/app.module.ts,添加全局拦截器提供者:

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
// 导入你的其他模块(比如PrismaModule)

@Module({
  imports: [/* 你的业务模块、Prisma模块 */],
  controllers: [/* 你的控制器 */],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: TransformInterceptor,
    },
  ],
})
export class AppModule {}

方式2:在main.ts中注册

修改 src/main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
import { Reflector } from '@nestjs/core';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 注册全局拦截器
  app.useGlobalInterceptors(new TransformInterceptor(app.get(Reflector)));
  await app.listen(3000);
}
bootstrap();

三、在控制器中使用

现在控制器方法可以直接返回Prisma查询结果,拦截器会自动包装成目标结构。如果需要自定义响应消息,使用@ResponseMessage装饰器即可:

import { Controller, Get, Param } from '@nestjs/common';
import { PrismaService } from './prisma.service';
import { ResponseMessage } from './common/interceptors/transform.interceptor';

@Controller('users')
export class UsersController {
  constructor(private readonly prisma: PrismaService) {}

  @Get(':id')
  @ResponseMessage('User data retrieved')
  async getUser(@Param('id') id: string) {
    // 直接返回Prisma查询结果,无需手动包装
    return this.prisma.user.findUnique({
      where: { id: Number(id) },
    });
  }
}

四、扩展优化建议

  • 自定义data字段:如果不同接口需要不同的data子字段(比如post、product),可以再创建一个@ResponseDataKey('post')装饰器,在拦截器中获取该值替换默认字段名。
  • 错误响应统一:如果需要统一错误格式,可以创建全局异常过滤器,将错误信息也包装成类似结构。
  • 空数据处理:在拦截器中添加逻辑,当查询结果为null时,返回data: { user: null }这类更友好的格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:25:24