Express + TypeScript 实战:用 Zod 做接口参数校验并自动生成 Swagger 文档
·
Express + TypeScript 实战:用 Zod 做接口参数校验并自动生成 Swagger 文档
1. 环境准备
安装核心依赖:
npm install express zod @zod-openapi/core swagger-jsdoc swagger-ui-express
npm install -D typescript ts-node @types/express
配置 tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true
}
}
2. 基础 Express 应用
创建 src/app.ts:
import express from 'express';
const app = express();
app.use(express.json());
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
3. Zod 参数校验
定义用户注册的校验规则 (src/schemas/user.ts):
import { z } from 'zod';
export const UserSchema = z.object({
username: z.string().min(3),
email: z.string().email(),
password: z.string().min(8),
age: z.number().int().positive().optional()
});
export type User = z.infer<typeof UserSchema>;
4. 集成 Swagger 文档
配置 Swagger (src/swagger.ts):
import swaggerJSDoc from 'swagger-jsdoc';
import { generateSchema } from '@zod-openapi/core';
import { UserSchema } from './schemas/user';
// 将 Zod 模式转为 OpenAPI 格式
const userSchema = generateSchema(UserSchema);
const options: swaggerJSDoc.Options = {
definition: {
openapi: '3.0.0',
info: {
title: 'User API',
version: '1.0.0'
},
components: {
schemas: {
User: userSchema
}
}
},
apis: ['./src/**/*.ts']
};
export const swaggerSpec = swaggerJSDoc(options);
5. 创建带校验的路由
实现用户注册接口 (src/routes/user.ts):
import { Router } from 'express';
import { UserSchema } from '../schemas/user';
import { validate } from '@zod-openapi/core';
const router = Router();
/**
* @openapi
* /users:
* post:
* summary: 注册新用户
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* responses:
* 201:
* description: 用户创建成功
* 400:
* description: 参数校验失败
*/
router.post('/users', (req, res) => {
const result = validate(UserSchema, req.body);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.issues
});
}
// 实际业务逻辑 (示例)
const userData = result.data;
res.status(201).json({
message: 'User created',
user: { ...userData, id: '123' }
});
});
export default router;
6. 最终集成
更新 src/app.ts:
import express from 'express';
import swaggerUI from 'swagger-ui-express';
import { swaggerSpec } from './swagger';
import userRouter from './routes/user';
const app = express();
// 路由
app.use(userRouter);
// Swagger 文档
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerSpec));
// 其他配置...
7. 运行与验证
- 启动服务:
npx ts-node src/app.ts
- 访问文档:
http://localhost:3000/api-docs
- 测试接口:
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{
"username": "john_doe",
"email": "john@example.com",
"password": "secure123"
}'
关键优势
- 类型安全:Zod 与 TypeScript 深度集成,提供编译时和运行时校验
- 文档自动化:通过
@zod-openapi/core自动生成 OpenAPI 规范 - 错误处理:自动返回详细的校验错误信息
- 代码复用:校验逻辑和文档定义使用同一套 Schema
常见问题解决
问题: 自定义错误消息
方案: 在 Zod Schema 中配置:
z.string().min(8, { message: '密码至少8个字符' })
问题: 处理嵌套对象
方案: 使用 z.object() 嵌套:
const AddressSchema = z.object({
city: z.string(),
street: z.string()
});
const UserSchema = z.object({
// ...其他字段,
address: AddressSchema
});
问题: 文件上传校验
方案: 使用中间件处理 multipart 数据:
import multer from 'multer';
const upload = multer();
router.post('/avatar',
upload.single('avatar'),
(req, res) => {
// 处理文件
}
);
更多推荐
所有评论(0)