GraphQL查询中Date字段返回null但数据库存在对应数据
解决PostgreSQL Timestamp通过GraphQL传输后变为Null的问题
你遇到的核心问题是日期类型在GraphQL序列化/反序列化链路中的不兼容:TypeORM从PostgreSQL拿到的是Date对象,但GraphQL默认会把它序列化为ISO格式的字符串,而Service1在接收时没有正确将这个字符串转回Date类型,最终导致字段被解析为null。手动遍历转对象确实不是优雅的长期方案,下面给你几个更合理的解决思路:
1. 配置GraphQL客户端自动解析日期
如果Service1使用Apollo Client这类常见的GraphQL客户端,可以通过自定义缓存策略,让客户端自动把ISO日期字符串转成Date对象,一劳永逸解决所有同类型字段的转换:
// Service1的Apollo Client配置示例 import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; const httpLink = createHttpLink({ uri: 'http://service2/graphql', // 替换为你的Service2 GraphQL地址 }); // 自定义字段解析规则,自动转换日期 const cache = new InMemoryCache({ typePolicies: { // 替换为你的实体类型名称(和GraphQL schema中定义的一致) YourEntity: { fields: { executed_on: { read(value) { // 若返回值是ISO字符串,自动转为Date对象 return typeof value === 'string' ? new Date(value) : value; }, }, }, }, }, }); const client = new ApolloClient({ link: httpLink, cache, });
2. 在Service2中自定义GraphQL日期标量
如果默认的GraphQLISODateTime处理逻辑不符合你的需求,可以在Service2中自定义一个日期标量,严格控制序列化和反序列化的规则:
// Service2中自定义DateTime标量 import { GraphQLScalarType, Kind } from 'graphql'; export const DateTimeScalar = new GraphQLScalarType({ name: 'DateTime', description: '自定义日期时间标量,支持Date对象与ISO字符串双向转换', serialize(value: Date) { // 把Date对象序列化为标准ISO字符串 return value.toISOString(); }, parseValue(value: string) { // 处理客户端传入的字符串(Mutation场景) return new Date(value); }, parseLiteral(ast) { // 解析GraphQL查询中的字面量参数 if (ast.kind === Kind.STRING) { return new Date(ast.value); } return null; }, });
然后在你的实体字段中替换默认的GraphQLISODateTime:
@Column({ nullable: true, type: 'timestamp' }) @Field(() => DateTimeScalar, { nullable: true }) executed_on: Date;
3. 用Class-Transformer实现自动类型转换
如果Service1是TypeScript项目,可以借助class-transformer库,在DTO(数据传输对象)中配置自动转换,不用手动处理每一个字段:
首先安装依赖:
npm install class-transformer class-validator
然后在Service1的实体DTO中添加转换装饰器:
import { Transform } from 'class-transformer'; class YourEntityDTO { // 其他字段... @Transform(({ value }) => typeof value === 'string' ? new Date(value) : value) executed_on?: Date; }
最后在拿到GraphQL响应后,用plainToClass完成转换:
import { plainToClass } from 'class-transformer'; // 假设response是从Service2获取的GraphQL响应数据 const entity = plainToClass(YourEntityDTO, response.data.yourEntity);
这几个方案都能避免手动遍历的繁琐,而且可以复用在后续的REST API或其他GraphQL场景中,更符合工程化的设计思路。
内容的提问来源于stack exchange,提问作者BURGERFLIPPER101
相关产品推荐
相关产品推荐

