【问题标题】:Java Programmatically send GraphQL REST QueryJava 以编程方式发送 GraphQL REST 查询
【发布时间】:2017-10-29 11:36:14
【问题描述】:

我是 GraphQL 的新手,我正在尝试弄清楚如何以编程方式发送我在单独的微服务中实现的 GraphQL POST 查询。

在我的主应用程序中,我使用 Java + Spring REST 模板发送查询,同时将 POST 正文附加为字符串 GraphQL 查询,例如

String body = "query MyLearner {learner(id: 1) {lastName givenName} learners { givenName }}";

我可以在我的 play-scala 微服务中接收查询,但无法解析 JSON。

接收方式:

def graphqlBody(tenant: Int) = Action.async(parse.json) { request ⇒
    val query = (request.body \ "query").as[String]
    val operation = (request.body \ "operationName").asOpt[String]

    val variables = (request.body \ "variables").toOption.flatMap {
      case JsString(vars) ⇒ Some(parseVariables(vars))
      case obj: JsObject ⇒ Some(obj)
      case _ ⇒ None
    }

    executeQuery(query, variables, operation)
}

注意,我基本上尝试使用我的域模型来实现 GraphQL Sangria 代码,因此它可能看起来与人相似。 sangria

我在解析 JSON 时在该方法的第 1 行遇到错误我假设这是因为传入的 JSON 主体不是有效的 JSON,因为它是 GraphQL 格式,但这是用于 Sangria 并且适用于 Sangria 所以不是确定为什么它在这里不起作用。

play.api.http.HttpErrorHandlerExceptions$$anon$1: 执行异常[[JsResultException: JsResultException(errors:List((,List(ValidationError(List("query MyLearner {learner(id: 1) {lastName givenName}) { givenName }}" 不是对象),WrappedArray())))))]]

收到的 JSON 正文的调试屏幕截图:

感谢@Ra Ka 的指导,我能够提出正确的查询,请参阅下面的答案:

{  
   "variables":{  
      "id":1
   },
   "operationName":"MyLearner",
   "query":"query MyLearner($id: Long!) {learner(id: $id) {misId givenName}}"
}

【问题讨论】:

  • 该方法收到的请求正文是什么?正如你所说,似乎播放无法解码你的 json
  • 我已经用 JSON 正文的屏幕截图更新了问题。

标签: json scala playframework graphql


【解决方案1】:

您提供的 graphql 查询格式错误。实际的graphql 查询不是有效的JSON 格式,您提供的是该格式,因此您肯定会得到无效的 JSON 异常。因此,您需要提供graphql 查询作为值而不是正文。由于您的接收方法是解析queryopertionNamevariables字段,您需要提供以下格式的请求正文:

{
    "variables": {
        "id": "123"
    },
    "operationName":"MyLearner",
    "query": "query MyLearner {learner($id: String) {lastName givenName} learners { givenName }}"
}

如果您想了解更多关于变量和操作名称等查询的信息,请参考here

另外,我在学习graphql的时候,对 operationName 理解有困难,如果你知道的话,忽略这个。 OperationName 用于从query 字段中已有的多个查询中进行选择。例如:

{
    "variables": {
        "id": "123"
    },
    "operationName":"Query1" or "Query2" //provide either of query to get data so that you can write single query for all data fetching and provide operationName for each type of data,
    "query": "query Query1 {learner($id: String) {lastName givenName} learners { givenName }} query Query2 {learner($id: String) learners { givenName }}"
    }

【讨论】:

  • 谢谢老兄,我无法从我遵循的教程中清楚地看出这一点。非常感谢!
  • 嘿@Ra Ka,您的回答有一些小错误,但我能够弄清楚。如果您想将答案更新为与我的相似,我会用答案更新我的帖子,因为您应该获得大部分功劳。
猜你喜欢
  • 2016-08-23
  • 2022-08-21
  • 2012-04-21
  • 2011-08-07
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多