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

如何将TypeScript DTO类转换为Fastify Swagger可用的JSON Schema

问题原因
  • class-transformer的classToPlain方法定位是将类实例转换为纯JS对象,用于序列化场景,本身不具备生成JSON Schema的能力
  • 你传入的是TodoDTO类构造函数本身,而非类的实例,因此输出结果是函数对象,和预期完全不符
可行解决方案

方案1:基于现有class-validator生态生成Schema

适配你已经使用的class-validator装饰器,使用class-validator-jsonschema工具直接从装饰器元数据生成标准JSON Schema

  1. 安装依赖
npm install class-validator-jsonschema
  1. 代码示例
import { IsNumber, IsString, getMetadataStorage, IsOptional } from 'class-validator';
import { validationMetadatasToSchemas } from 'class-validator-jsonschema';

export class TodoDTO {
    // 字段必填去掉?可选符,可选的话加@IsOptional()装饰器即可
    @IsNumber()
    id: number;

    @IsString()
    name: string;

    @IsString()
    description: string;
}

// 批量生成所有带class-validator装饰器的类的Schema
const schemas = validationMetadatasToSchemas({
  refPointerPrefix: '#/components/schemas/',
  metadataStorage: getMetadataStorage(),
});

// 你需要的TodoDTO Schema就在schemas.TodoDTO中
console.log(schemas.TodoDTO);
  1. Fastify中集成使用
    把生成的Schema注册到Fastify实例,之后直接在路由校验规则里引用即可:
import fastify from 'fastify';

const app = fastify();

// 批量注册生成的Schema
for (const [schemaName, schema] of Object.entries(schemas)) {
  app.addSchema({
    $id: schemaName,
    ...schema
  });
}

// 路由中直接引用Schema做校验
app.post('/todo', {
  schema: {
    body: { $ref: 'TodoDTO#' }
  }
}, async (req, res) => {
  const todo = req.body as TodoDTO;
  // 后续业务逻辑
})

提示:class-validator不会自动读取TS的可选符?生成规则,如果你需要字段可选,必须给对应字段加上@IsOptional()装饰器,否则生成的JSON Schema会默认将所有带校验装饰器的字段放到required数组中。

方案2:使用Fastify生态原生推荐的TypeBox定义

如果可以调整现有DTO定义方式,更推荐使用@sinclair/typebox,它可以同时生成JSON Schema和TypeScript类型,和Fastify兼容性更好,不需要额外的装饰器和元数据解析:

import { Type, Static } from '@sinclair/typebox';
import fastify from 'fastify';

const app = fastify();

// 定义Schema的同时生成对应的TS类型
export const TodoDTO = Type.Object({
  id: Type.Number(),
  name: Type.String(),
  description: Type.String()
  // 可选字段用Type.Optional包裹:description: Type.Optional(Type.String())
});
export type TodoDTO = Static<typeof TodoDTO>;

// 路由中直接传入Schema即可生效
app.post('/todo', {
  schema: {
    body: TodoDTO
  }
}, async (req, res) => {
  const todo = req.body as TodoDTO;
  // 后续业务逻辑
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:15:04