我在将一些数据从 PostgreSQL 数据库传输到服务时遇到问题。
设置方式是这样的:
Service1 向 Service2 发送 GraphQL 请求以请求数据。 Service2 将此数据存储在 PostgreSQL 数据库中,并从中获取信息。
数据被建模为带有 TypeORM 和 GraphQL 装饰器的实体。我遇到问题的确切字段是:
@Column({
nullable: true,
type: 'timestamp'
})
@Field(() => GraphQLISODateTime, {nullable: true})
executed_on: Date
当数据从数据库到达service2时,它存在,所有字段都存在,并且日期字段及其值存在。
从数据库获取时的字段:
"executed_on": "2019-10-27T23:00:00.000Z"
从Service1获取时的字段:
"executed_on": null
当它发送到 service1 时,我可以 console.log 数据并看到那里的字段。我假设由于 GraphQL 以 JSON 格式发送数据,因此日期字段变成了字符串。现在,当此数据从 service1 传输到其他地方时,所有
executed_on
字段值都变为空。我不知道为什么会出现这种情况。难道是因为现在它是一个字符串,所以它没有被解析到日期字段中?
我发现的一个解决方法是循环遍历数组中的每个对象,并简单地从当前字符串值创建一个新的 Date 对象,但这不是我想要做的事情,因为当我获取时,这个过程也在其他服务中发生来自外部 REST API 的数据,所以我猜这会是一个糟糕的设计?我对此很陌生。
如有任何帮助,我们将不胜感激。
我面临着类似的问题,我相信这是由于 DateTime 类型的 GraphQl 节点模块中的序列化错误造成的。
这就是失败的地方:
// 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(...) 对象。
或者分叉原始存储库并将此代码添加到“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)
为了确保正确处理时间戳,您可以添加时间戳的自定义类型解析器。
在 PostgreSQL 中,数据类型是通过类型 OID(对象标识符)来标识的,1114 是时间戳数据类型的 OID 类型
const { types } = require('pg');
types.setTypeParser(1114, stringValue => new Date(stringValue + 'Z'));