我们有一个使用 Scalatra ( http://scalatra.org/ ) 作为我们的 Web 框架的 Scala 应用程序。我想知道是否有关于如何使用 Sangria(http://sangria-graphql.org/)和 Scalatra 实现 GraphQL 端点的任何好的(或只是任何)资源?
我是 Scala 的新手,如果有任何帮助,我将不胜感激。
我们有一个使用 Scalatra ( http://scalatra.org/ ) 作为我们的 Web 框架的 Scala 应用程序。我想知道是否有关于如何使用 Sangria(http://sangria-graphql.org/)和 Scalatra 实现 GraphQL 端点的任何好的(或只是任何)资源?
我是 Scala 的新手,如果有任何帮助,我将不胜感激。
我不知道,但由于 Scalatra 使用 json4s,你会使用桑格利亚汽酒的 json4s marshaller。
否则,如果桑格利亚汽酒对您来说更清楚,这里有一个 scala 工作表,其中包含一个非常简单的基于 off play + 桑格利亚汽酒的示例 - 在这种情况下,您只需要交换 json 库。
db 是模拟的(也许你使用 Slick?)和 http 服务器也是模拟的,但这是在函数定义中交换的一个简单案例。
import sangria.ast.Document
import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError}
import sangria.macros.derive.{ObjectTypeDescription, ObjectTypeName, deriveObjectType}
import sangria.parser.{QueryParser, SyntaxError}
import sangria.renderer.SchemaRenderer
import sangria.schema.{Argument, Field, IntType, ListType, ObjectType, OptionInputType, Schema, fields}
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Success}
// replace with another json lib
// eg https://github.com/sangria-graphql/sangria-json4s-jackson
import play.api.libs.json._
import sangria.marshalling.playJson._
case class User(name: String, age: Int, phone: Option[String])
class FakeDb {
class UsersTable {
def getUsers(limit: Int): List[User] = {
// this would come from the db
List(
User("john smith", 23, None),
User("Anne Schwazenbach", 45, Some("2134556"))
)
}
}
val usersRepo = new UsersTable
}
object MySchema {
val limitArg: Argument[Int] = Argument("first", OptionInputType(IntType),
description = s"Returns the first n elements from the list.",
defaultValue = 10)
implicit val UsersType: ObjectType[FakeDb, User] = {
deriveObjectType[FakeDb, User](
ObjectTypeName("Users"),
ObjectTypeDescription("Users in the system")
)
}
private val Query: ObjectType[FakeDb, Unit] = ObjectType[FakeDb, Unit](
"Query", fields[FakeDb, Unit](
Field("users", ListType(UsersType),
arguments = limitArg :: Nil,
resolve = c => c.ctx.usersRepo.getUsers(c.arg(limitArg))
)
))
val theSchema: Schema[FakeDb, Unit] = Schema(Query)
}
object HttpServer {
def get(): String = {
// Http GET
SchemaRenderer.renderSchema(MySchema.theSchema)
}
def post(query: String): Future[JsValue] = {
// Http POST
val variables = None
val operation = None
QueryParser.parse(query) match {
case Success(q) => executeQuery(q, variables, operation)
case Failure(error: SyntaxError) => Future.successful(Json.obj("error" -> error.getMessage))
case Failure(error: Throwable) => Future.successful(Json.obj("error" -> error.getMessage))
}
}
private def executeQuery(queryAst: Document, vars: Option[JsValue], operation: Option[String]): Future[JsValue] = {
val schema: Schema[FakeDb, Unit] = MySchema.theSchema
Executor.execute[FakeDb, Unit, JsValue](schema, queryAst, new FakeDb,
operationName = operation,
variables=vars.getOrElse(Json.obj()))
.map((d: JsValue) => d)
.recover {
case error: QueryAnalysisError ⇒ Json.obj("error" -> error.getMessage)
case error: ErrorWithResolver ⇒ Json.obj("error" -> error.getMessage)
}
}
}
HttpServer.get()
val myquery = """
{
users {
name
}
}
"""
val res: JsValue = Await.result(HttpServer.post(myquery), 10.seconds)