如何在响应中对Date进行序列化,同时不影响Swagger/OpenAPI?
我正在使用 nestjs-zod 包来进行请求/响应校验和Swagger生成,构建一个NestJS API。
我的领域实体如下:
export class UserEntity {
constructor(
public readonly id: string,
public readonly username: string,
public readonly hashPassword: string,
public readonly is_active: boolean,
public readonly created_at: Date,
public readonly updated_at: Date | null,
) {}
}
我的Zod响应模式如下:
import { z } from "zod"
import { createZodDto } from "nestjs-zod"
export const registerResponseSchema = z.object({
id: z.string(),
username: z.string(),
created_at: z.string(),
})
export class RegisterResponse extends createZodDto(registerResponseSchema) {}
控制器:
import { Body, Controller, Post } from '@nestjs/common'
import { ApiOperation, ApiTags } from '@nestjs/swagger'
import { ZodResponse } from 'nestjs-zod'
@ApiTags('Auth')
@Controller('auth')
export class AuthController {
constructor(private readonly register: RegisterUseCase) {}
@ApiOperation({ summary: 'Registrations' })
@ZodResponse({
status: 201,
type: RegisterResponse,
})
@Post('register')
async registration(@Body() body: RegisterRequest) {
return await this.register.register(body.username, body.password)
}
}
我的实体返回一个Date值:
created_at: Date
如果我把响应模式定义为:
created_at: z.string()
Swagger能正确工作,但运行时校验失败,因为返回的值是Date,而不是字符串。
如果我把模式改成:
created_at: z.date()
那么运行时校验可以通过,但Swagger生成功能会因为以下错误而失败:
Date cannot be represented in JSON Schema
因此,看起来不可能同时做到:
- 使用ZodResponse验证响应
- 生成Swagger/OpenAPI
- 在实体中保留Date
在使用nestjs-zod与 Swagger时,推荐的处理Date字段的方式是什么?
解决方案
使用z.coerce.date() 搭配自定义转换器,或使用z.string().datetime() 并进行序列化。
最简单的做法是在模式层将Date转换为字符串,这样就能同时满足运行时校验和Swagger的生成功能。
import { z } from "zod"
import { createZodDto } from "nestjs-zod"
export const registerResponseSchema = z.object({
id: z.string(),
username: z.string(),
created_at: z.preprocess(
(val) => (val instanceof Date ? val.toISOString() : val),
z.string().datetime()
),
})
export class RegisterResponse extends createZodDto(registerResponseSchema) {}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。