GraphQL响应中的自定义映射键

时间:2017-01-09 21:47:01

标签: php graphql graphql-php

我一直在研究GraphQL作为我的一些REST API的替代品,虽然我认为我已经围绕基础知识,就像我目前看到的大部分内容一样,有一个重要的特性似乎失踪。

假设我有一系列这样的项目:

{
    "id": "aaa",
    "name": "Item 1",
    ...
}

应用程序需要所有这些对象的映射,按ID索引:

{
    "allItems": {
        "aaa": {
            "name": "Item 1",
            ...
        },
        "aab": {
            "name": "Item 2",
            ...
        }
    }
}

我写过的每一个API都能够以这样的格式返回结果,但我很难找到一种方法来使用GraphQL。我一直在issue 101上运行,但这更多地涉及未知模式。就我而言,我确切地知道所有领域是什么;这纯粹是关于输出格式。我知道我可以简单地返回数组中的所有项目并在客户端重新格式化,但这看起来有点过分,因为它过去从未被需要,并且会使GraphQL感觉像向后退一步。我不确定我想要做的事情是不可能的,或者我只是使用了所有错误的术语。我应该继续挖掘,还是GraphQL不适合我的需求?如果可以,那么查询可能会像这样检索数据?

我目前正在服务器上使用graphql-php,但我对更高级别的概念响应持开放态度。

1 个答案:

答案 0 :(得分:7)

不幸的是,使用像这样的任意和动态键返回对象并不是GraphQL中的一流公民。这并不是说你不能达到同样的目的,但这样做会失去GraphQL的许多好处。

如果设置为返回具有id键的对象而不是返回包含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的事情。如果您只想尝试一下,我们会在scaphold.io上提供您可以使用的AnyObject类型。

希望这有帮助!