GraphQL 响应中的自定义映射键
我一直在研究 GraphQL 作为我的一些 REST API 的替代品,虽然我认为我已经把我的头放在了基础知识上,就像我目前看到的大部分内容一样,但有一个重要的功能似乎失踪.
I've been looking into GraphQL as a replacement for some REST APIs of mine, and while I think I've wrapped my head around the basics and like most of what I see so far, there's one important feature that seems to be missing.
假设我有一个这样的项目集合:
Let's say I've got a collection of items like this:
{
"id": "aaa",
"name": "Item 1",
...
}
应用程序需要所有这些对象的映射,按 ID 索引:
An application needs a map of all those objects, indexed by ID as such:
{
"allItems": {
"aaa": {
"name": "Item 1",
...
},
"aab": {
"name": "Item 2",
...
}
}
}
我写过的每个 API 都能够以这样的格式返回结果,但我正在努力寻找一种使用 GraphQL 实现的方法.我一直在运行 issue 101,但这更多地涉及未知模式.就我而言,我确切地知道所有字段是什么;这纯粹是关于输出格式.我知道我可以简单地返回数组中的所有项目并在客户端重新格式化它,但鉴于过去从未需要它,这似乎有点矫枉过正,而且会让 GraphQL 感觉像是倒退了一步.我不确定我想要做的事情是否不可能,或者我只是使用了所有错误的术语.我应该继续挖掘,还是 GraphQL 不适合我的需求?如果这是可能的,那么检索这样的数据的查询会是什么样子?
Every API I've ever written has been able to give results back in a format like this, but I'm struggling to find a way to do it with GraphQL. I keep running across issue 101, but that deals more with unknown schemas. In my case, I know exactly what all the fields are; this is purely about output format. I know I could simply return all the items in an array and reformat it client-side, but that seems like overkill given that it's never been needed in the past, and would make GraphQL feel like a step backwards. I'm not sure if what I'm trying to do is impossible, or I'm just using all the wrong terminology. Should I keep digging, or is GraphQL just not suited to my needs? If this is possible, what might a query look like to retrieve data like this?
我目前正在服务器上使用 graphql-php,但我是开放的到更高层次的概念反应.
I'm currently working with graphql-php on the server, but I'm open to higher-level conceptual responses.
推荐答案
不幸的是,像这样返回具有任意和动态键的对象并不是 GraphQL 中真正的一等公民.这并不是说你不能实现同样的事情,但这样做你会失去 GraphQL 的许多好处.
Unfortunately returning objects with arbitrary and dynamic keys like this is not really a first-class citizen in GraphQL. That is not to say you can't achieve the same thing, but in doing so you will lose many of the benefits of GraphQL.
如果您设置为返回带有 id 键的对象,而不是返回包含 id 的对象集合/列表,然后在客户端上进行转换,那么您可以创建一个特殊的 GraphQLScalarType.
If you are set on returning an object with id keys instead of returning a collection/list of objects containing the ids and then doing the transformation on the client then you can create a special 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;
}
});
这种方法的问题在于,由于它是标量类型,因此您无法提供选择集来查询它.例如.如果你有一个类型
The problem with this approach is that since it is a scalar type you cannot supply a selection set to query it. E.G. if you had a type
type MyType implements Node {
id: ID!
myKeyedCollection: AnyObject
}
那你就只能这样查询了
query {
getMyType(id: abc) {
myKeyedCollection # note there is no { ... }
}
}
正如其他人所说,我不推荐这样做,因为您失去了 GraphQL 的许多好处,但它表明 GraphQL 仍然可以做几乎 REST 可以做的任何事情.
As others have said, I wouldn't recommend this because you are losing a lot of the benefits of GraphQL but it goes to show that GraphQL can still do pretty much anything REST can.
希望这有帮助!
相关文章