Как я могу сериализовать ответы Sangria с помощью json4s и Akka HTTP?

Я работаю над небольшой вариацией Начало работы, используя Akka HTTP. Я пытаюсь использовать json4s-jackson в качестве библиотеки сериализации, но у меня возникают проблемы с получением ответа, который я хочу.

В частности, сериализованный ответ, который я получаю, представляет собой JSON-версию кортежа (StatusCode, Node):

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

Часть data верна, но, очевидно, я просто хочу это, а не первый элемент сериализованного кортежа.

Я использую https://github.com/hseeberger/akka-http-json/tree/master/akka-http-json4s/src, поэтому мой трейт с маршрутом выглядит так:

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
}

На всю жизнь я не могу понять, что не так. Я просматривал https://github.com/sangria-graphql/sangria-akka-http-example, но похоже, это то же самое, за исключением использования spray-json вместо json4s.

Идеи? Спасибо!


person David van Geest    schedule 27.10.2017    source источник


Ответы (2)


А, разобрался. я забыл добавить

import sangria.marshalling.json4s.jackson._

к признаку, определяющему маршрут. Добавление делает свое дело.

person David van Geest    schedule 27.10.2017

Просто хотел предоставить быстрое обновление этого ответа для полного GraphQLRRequest. Теперь переменные включены в запрос.

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

  }
person JTW    schedule 09.03.2018