如何使用json4s和Akka HTTP序列化Sangria响应?

时间:2017-10-27 18:09:03

标签: scala graphql akka-http json4s sangria

我正在使用Akka HTTP轻微改变Sangria的Getting Started。我正在尝试使用json4s-jackson作为序列化lib,但是在遇到我想要的响应时遇到了一些麻烦。

具体来说,我得到的序列化响应是(StatusCode, Node)元组的JSON版本:

{
    "_1": {
        "allowsEntity": true, 
        "defaultMessage": "OK", 
        "intValue": 200, 
        "reason": "OK"
    }, 
    "_2": {
        "data": {
            "foo": {
                "id": "1", 
                "name": "Foo"
            }
        }
    }
}

data部分是正确的,但显然我只是想要那个,而不是序列化元组的第一个元素。

我正在使用akka-http-json4s,所以我的路线特征如下:

case class GraphQlData(query: String, operation: Option[String])

trait FooController {
  import de.heikoseeberger.akkahttpjson4s.Json4sSupport._

  implicit val serialization = jackson.Serialization
  implicit val formats = DefaultFormats

  val fooRoutes = post {
    entity(as[GraphQlData]) { data =>
      QueryParser.parse(data.query) match {

        // query parsed successfully, time to execute it!
        case Success(queryAst) =>
          complete {
            Executor
              .execute(
                SchemaDefinition.FooSchema,
                queryAst,
                new FooService,
                operationName = data.operation
              )
              .map(OK -> _)
              .recover {
                case error: QueryAnalysisError => BadRequest -> error.resolveError
                case error: ErrorWithResolver  => InternalServerError -> error.resolveError
              }
          }

        // can't parse GraphQL query, return error
        case Failure(error) =>
          complete(BadRequest -> error.getMessage)
      }
    }
  }

  implicit def executionContext: ExecutionContext
}

对于我的生活,我无法弄清楚出了什么问题。我一直在关注sangria-akka-http-example但它看起来完全一样,除了使用spray-json而不是json4s。

想法?谢谢!

2 个答案:

答案 0 :(得分:0)

啊,想通了。我忽略了添加

import sangria.marshalling.json4s.jackson._

定义路线的特征。添加它就可以了。

答案 1 :(得分:0)

只想为完整的GraphQLRequest提供此答案的快速更新。现在变量包含在请求中。

import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import org.json4s._
import org.json4s.JsonAST.JObject
import sangria.marshalling.json4s.jackson._

case class GQLRequest(query: String, operationName: Option[String], variables: JObject)

trait SomeJsonSupport extends Json4sSupport {
    implicit val serialization = jackson.Serialization
    implicit val formats = DefaultFormats

}

trait GraphQLResource extends SomeJsonSupport{
  implicit val timeout:Timeout
  implicit val system:ActorSystem
  import system.dispatcher

  def graphqlRoute: Route =
    (post & path("graphql")) {
      entity(as[GQLRequest]) { requestJson =>
        println(s"This is the requestJson = $requestJson")
        graphQLEndpoint(requestJson)
      }
    } ~
      get {
        println(s"This is working")
        getFromResource("graphiql.html")
      }


  def graphQLEndpoint(requestJson: GQLRequest): Route = {
    val route = QueryParser.parse(requestJson.query) match {
      case Success(query) =>
        println(s"This is the query $query")


        val vars = requestJson.variables match {
          case jObj:JObject => jObj
          case _ => JObject(List.empty)
        }

        val futureJValue = Executor.execute(clientSchema,
          query,
          NclhGqlRequest(this),
          operationName = requestJson.operationName,
          variables = vars)

        val futureTupleStatusCodeJValue = futureJValue.map(OK -> _).recover {
          case error: QueryAnalysisError => BadRequest -> error.resolveError
          case error: ErrorWithResolver => InternalServerError -> error.resolveError
        }
        complete(futureTupleStatusCodeJValue)

      case Failure(error) =>
        complete(BadRequest, error.getMessage)
    }
    route

  }