Java GraphQL - 将字段值传递给对象的解析器

Posted

技术标签:

【中文标题】Java GraphQL - 将字段值传递给对象的解析器【英文标题】:Java GraphQL - Pass field values to resolver for objects 【发布时间】:2017-10-24 21:05:48 【问题描述】:

我希望使用另一种对象类型将字段值传递给已解析的字段。

如果我有“客户 > 用户 > 个人资料”,另一种说法 - 我如何将客户中的客户 ID 字段值作为参数或变量传递给个人资料以便正确解析?

【问题讨论】:

没有代码或其他有关您正在使用的信息的信息。我没有使用任何用于 Java 的 GraphQL 库,所以 YMMV 但通常您会将此信息附加到您为每个解析点返回的值中。当你从Customer 得到User 时,它应该携带来自Customer 的一些(或全部)数据,同样也传送到Profile,所以(天真地)你可能会做一些事情((Profile)resolveParams.getSource()).getUser().getCustomer().getId() 【参考方案1】:

正好有 5 种可能性(从 graphql-java v12 开始)向任何级别的解析器 (DataFetcher) 提供信息:

1) 直接在查询中传递它们(可能在多个级别上):

customer(id: 3) 
      user 
         profile(id: 3) 
             name
         
      
   

2) 从对象中获取值

source 是封闭查询的结果。 在您的情况下,customer 查询的来源是根(无论您在查询执行时提供什么,例如

graphQL.execute(ExecutionInput.newExecutionInput()
    .query(query)
    .root(root)
    .build())

user 查询的来源是返回的任何 customer 查询,可能是一些 Customer 实例。profile 查询的来源是 user 查询返回的任何内容,可能是 User 实例。 您可以通过DataFetchingEnvironment#getSource() 获取源代码。因此,如果User 包含您想要的CustomerID,只需通过((User) env.getSource()).getCustomerId() 获取它。如果没有,请考虑将结果包装到一个对象中,该对象将包含您在子查询中需要的所有内容。

3) 使用共享上下文传递值

graphql-java 如果您不自己提供自定义上下文,将为您提供GraphQLContext 的实例。因此,在customerDataFetcher 中,您可以将CustomerID 存储到其中:

Customer customer = getCustomer();
GraphQLContext context = env.getContext();
context.put("CustomerID", customer.getId());

稍后,在DataFetcher for profile 中,您可以从上下文中获取它:

GraphQLContext context = env.getContext();
context.get("CustomerID");

要提供自定义上下文,请在执行查询时传递它:

ExecutionInput input = ExecutionInput.newExecutionInput()
  .query(operation)
  .context(new ConcurrentHashMap<String, Object>())
  .build()
graphQL.execute(query, input);

您可以使用类型化对象而不是 ConcurrentHashMap,但您必须确保字段是 volatile 或 getters/setters synchronized 或其他线程安全的。

这种方式是有状态的,因此最难管理,所以只有在其他方法都失败时才使用它。

4) 直接获取传递给父字段的参数(可能从 graphql-java v11 开始)

ExecutionStepInfo stepInfo = dataFetchingEnvironment.getExecutionStepInfo();
stepInfo.getParent().getArguments(); // get the parent arguments

5) 使用 local 上下文传递值(可能从 graphql-java v12 开始)

不是直接返回结果,而是将其包装成DataFetcherResult。这样,您还可以将任何对象附加为 localContext,所有子 DataFetchers 都可以通过 DataFetchingEnvironment#getLocalContext() 使用该对象

【讨论】:

非常感谢!您能否添加有关使用一种或另一种方式的一些用例的信息?在所有这些方法中,哪种方式更可取? @Max 如果可以自然地将值表示为父级的属性,#2 是最简单的。如果不是,并且值很简单(不需要反序列化),#4 很好。除了这些,#5 很好。 #1 和 #3 不太可取。

以上是关于Java GraphQL - 将字段值传递给对象的解析器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 GraphQL 突变中使用 FaunaDB 将数组传递给字段

GraphQL - 将枚举值作为参数直接传递给突变?

如何将 JSONObject 值分配给 graphql 模式文件中的字段?

NodeJS:将字段值从 ResolverQuery 传递到另一个 JS 文件

如何将请求标头传递给 graphql 解析器

如何将模型字段传递给 JsonResponse 对象