【问题标题】:Custom map keys in GraphQL responseGraphQL 响应中的自定义映射键
【发布时间】:2017-05-24 06:37:21
【问题描述】:

我一直在研究 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,但我愿意接受更高级别的概念响应。

【问题讨论】:

  • “并且会让 GraphQL 感觉像是倒退了一步”——在您的情况下,也许您知道 Web 服务的每个客户端都需要什么。否则,您会假设地图是客户需要的。需要与 Web 服务返回的内容相反的客户端必须进行某种转换。恕我直言,是否返回地图或数组样式集合的决定是一种清洗,因为客户想要一个或另一个是 50:50。
  • @CommonsWare 我目前想到的 API 仅在组织内部使用,所以是的,我可以肯定地说,所有客户都需要他们一直获得的格式的数据它在页面加载时调用,作为本地搜索的快速索引,并根据需要检索扩展的项目详细信息(以 GraphQL 易于表示的格式)。问题只是我想要做的事情是否可行。
  • “所有客户都需要他们一直采用的格式的数据”——在大多数现代编程语言中,将集合转换为地图需要 1-3 行代码。 “是 GraphQL 不适合我的需求吗?” -- 如果您要求 Web 服务返回特定的 JSON 结构,那么 GraphQL 不适合。即使您通过了这个案例(而且我不知道解决方案),您也会遇到其他问题。您对 JSON 的结构没有绝对的控制权,这由模式决定,并且模式不是为处理任意结构而设计的。

标签: php graphql graphql-php


【解决方案1】:

不幸的是,像这样返回具有任意和动态键的对象并不是 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 可以做的任何事情。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2010-09-05
    • 1970-01-01
    • 2020-07-03
    • 2020-02-07
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多