如何将TypeScript DTO类转换为Fastify Swagger可用的JSON Schema
问题原因
class-transformer的classToPlain方法定位是将类实例转换为纯JS对象,用于序列化场景,本身不具备生成JSON Schema的能力- 你传入的是
TodoDTO类构造函数本身,而非类的实例,因此输出结果是函数对象,和预期完全不符
可行解决方案
方案1:基于现有class-validator生态生成Schema
适配你已经使用的class-validator装饰器,使用class-validator-jsonschema工具直接从装饰器元数据生成标准JSON Schema
- 安装依赖
npm install class-validator-jsonschema
- 代码示例
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);
- 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
相关产品推荐
相关产品推荐

