尽管存在数据,但在 GraphQL 查询中日期字段返回为空
Posted
技术标签:
【中文标题】尽管存在数据,但在 GraphQL 查询中日期字段返回为空【英文标题】:Date field returned as null on GraphQL query despite data existing 【发布时间】:2020-02-25 14:01:10 【问题描述】:我在将一些数据从 PostgreSQL 数据库传输到服务时遇到问题。
设置方式是这样的:
Service1 向 Service2 发送 GraphQL 请求,请求数据。 Service2 将此数据存储在 PostgreSQL 数据库中,从中获取信息。
数据被建模为带有来自 TypeORM 和 GraphQL 的装饰器的实体。我遇到问题的确切字段是:
@Column(
nullable: true,
type: 'timestamp'
)
@Field(() => GraphQLISODateTime, nullable: true)
executed_on: Date
当数据从 DB 到达 service2 时,它存在,所有字段都存在,并且日期字段及其值存在。
从数据库获取时的字段:
"executed_on": "2019-10-27T23:00:00.000Z"
从Service1获取时的字段:
"executed_on": null
当它被发送到 service1 时,我可以 console.log 数据并看到那里的字段。我假设由于 GraphQL 以 JSON 格式发送数据,因此日期字段变为字符串。现在,当此数据从 service1 传输到其他位置时,所有 executed_on
字段值都变为空。我不知道发生这种情况的原因是什么。难道是因为它现在是一个字符串,它没有被解析到 Date 字段中?
我发现的一种解决方法是循环遍历数组中的每个对象,并简单地从当前字符串值创建一个新的 Date 对象,但这不是我希望做的事情,因为这个过程也发生在另一个服务中,当我正在从外部 REST API 获取数据,所以我猜这将是糟糕的设计?我对此很陌生。
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:我遇到了类似的问题,我认为这是由于 GraphQl 节点模块中 DateTime 类型的序列化错误。
这就是失败的原因:
// node_modules/graphql/execution/execute.js:
completeLeafValue(returnType, result)
// this returns null even though a correct "value" is being passed in
var serializedResult = returnType.serialize(result);
...
因为它的序列化器由于“value instanceof Date”而失败并且简单地返回null:
serialize(value)
return value instanceof Date ? value.toISOString() : null;
由于某种原因 type=Date 被强制转换为 "DateTime" 为什么我还没有弄清楚但在我看来它应该抛出一个错误而不是只返回 null。
正如您已经说过的:唯一的解决方法/修复是为对象树中的每个 Date 字段创建一个新的 Date(...) 对象。
或者 fork 原始存储库并将此代码添加到“completeLeafValue”方法中:
//node_modules/graphql/execution/execute.js:
completeLeafValue(returnType, result)
var serializedResult = returnType.serialize(result);
if(completeLeafValue==="DateTime")
result = new Date(result);
//new Date(...) does not throw and only returns null when it fails
//so we have to check for null
if(result === null)
throw new Error(`Cannot cast $result to Date object`);
...(rest or original fn)
【讨论】:
以上是关于尽管存在数据,但在 GraphQL 查询中日期字段返回为空的主要内容,如果未能解决你的问题,请参考以下文章
使用 Sequelize 在 GraphQL 查询中将日期时间字段输出为字符串