GraphQL 响应中的自定义映射键
Custom map keys in GraphQL response
我一直在研究 GraphQL 作为我的一些 REST API 的替代品,虽然我认为我已经了解了基础知识并且喜欢我目前看到的大部分内容,似乎缺少一项重要功能。
假设我收集了这样的项目:
{
"id": "aaa",
"name": "Item 1",
...
}
应用程序需要所有这些对象的映射,按 ID 索引:
{
"allItems": {
"aaa": {
"name": "Item 1",
...
},
"aab": {
"name": "Item 2",
...
}
}
}
我写过的每一个 API 都能够以这样的格式返回结果,但我正在努力寻找一种使用 GraphQL 来实现的方法。我在 issue 101 中保留 运行,但这更多地涉及未知模式。就我而言,我确切地知道所有字段是什么;这纯粹是关于输出格式。我知道我可以简单地 return 数组中的所有项目并在客户端重新格式化它,但这似乎有点过分,因为过去从来不需要它,并且会让 GraphQL 感觉像是倒退了一步。我不确定我正在尝试做的事情是不可能的,还是我只是使用了所有错误的术语。我应该继续挖掘,还是 GraphQL 不适合我的需求?如果这可能的话,检索这样的数据的查询可能是什么样的?
我目前正在服务器上使用 graphql-php,但我愿意接受更高级别的概念响应。
不幸的是,像这样返回具有任意和动态键的对象并不是 GraphQL 中真正的第一个 class 公民。这并不是说您无法实现相同的目标,但这样做您将失去 GraphQL 的许多优势。
如果您设置返回一个带有 id 键的对象,而不是返回 collection/list 个包含 id 的对象,然后在客户端上进行转换,那么您可以创建一个特殊的 GraphQLScalarType。
const GraphQLAnyObject = new GraphQLScalarType({
name: 'AnyObject',
description: 'Any JSON object. This type bypasses type checking.',
serialize: value => {
return value;
},
parseValue: value => {
return value;
},
parseLiteral: ast => {
if (ast.kind !== Kind.OBJECT) {
throw new GraphQLError("Query error: Can only parse object but got a: " + ast.kind, [ast]);
}
return ast.value;
}
});
这种方法的问题在于,由于它是标量类型,您无法提供选择集来查询它。例如。如果你有类型
type MyType implements Node {
id: ID!
myKeyedCollection: AnyObject
}
那你就只能这样查询了
query {
getMyType(id: abc) {
myKeyedCollection # note there is no { ... }
}
}
正如其他人所说,我不推荐这样做,因为您正在失去 GraphQL 的很多好处,但它表明 GraphQL 仍然可以做 REST 可以做的几乎所有事情。
希望对您有所帮助!
我一直在研究 GraphQL 作为我的一些 REST API 的替代品,虽然我认为我已经了解了基础知识并且喜欢我目前看到的大部分内容,似乎缺少一项重要功能。
假设我收集了这样的项目:
{
"id": "aaa",
"name": "Item 1",
...
}
应用程序需要所有这些对象的映射,按 ID 索引:
{
"allItems": {
"aaa": {
"name": "Item 1",
...
},
"aab": {
"name": "Item 2",
...
}
}
}
我写过的每一个 API 都能够以这样的格式返回结果,但我正在努力寻找一种使用 GraphQL 来实现的方法。我在 issue 101 中保留 运行,但这更多地涉及未知模式。就我而言,我确切地知道所有字段是什么;这纯粹是关于输出格式。我知道我可以简单地 return 数组中的所有项目并在客户端重新格式化它,但这似乎有点过分,因为过去从来不需要它,并且会让 GraphQL 感觉像是倒退了一步。我不确定我正在尝试做的事情是不可能的,还是我只是使用了所有错误的术语。我应该继续挖掘,还是 GraphQL 不适合我的需求?如果这可能的话,检索这样的数据的查询可能是什么样的?
我目前正在服务器上使用 graphql-php,但我愿意接受更高级别的概念响应。
不幸的是,像这样返回具有任意和动态键的对象并不是 GraphQL 中真正的第一个 class 公民。这并不是说您无法实现相同的目标,但这样做您将失去 GraphQL 的许多优势。
如果您设置返回一个带有 id 键的对象,而不是返回 collection/list 个包含 id 的对象,然后在客户端上进行转换,那么您可以创建一个特殊的 GraphQLScalarType。
const GraphQLAnyObject = new GraphQLScalarType({
name: 'AnyObject',
description: 'Any JSON object. This type bypasses type checking.',
serialize: value => {
return value;
},
parseValue: value => {
return value;
},
parseLiteral: ast => {
if (ast.kind !== Kind.OBJECT) {
throw new GraphQLError("Query error: Can only parse object but got a: " + ast.kind, [ast]);
}
return ast.value;
}
});
这种方法的问题在于,由于它是标量类型,您无法提供选择集来查询它。例如。如果你有类型
type MyType implements Node {
id: ID!
myKeyedCollection: AnyObject
}
那你就只能这样查询了
query {
getMyType(id: abc) {
myKeyedCollection # note there is no { ... }
}
}
正如其他人所说,我不推荐这样做,因为您正在失去 GraphQL 的很多好处,但它表明 GraphQL 仍然可以做 REST 可以做的几乎所有事情。
希望对您有所帮助!