以下Scala代码编译:
import spray.json.DefaultJsonProtocol._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.server.Directives.complete
case class Item(name: String, id: Long)
implicit val itemFormat = jsonFormat2(Item)
val item = Item("xbox", 123)
complete(item)
在工作表中使用以下输出:
import spray.json.DefaultJsonProtocol._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.server.Directives.complete
defined class Item
itemFormat: spray.json.RootJsonFormat[Item] = spray.json.ProductFormatsInstances$$anon$2@4528e00
item: Item = Item(xbox,123)
res0: akka.http.scaladsl.server.StandardRoute = <function1>
但是当我注释掉import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
时,我收到以下编译错误:
Error:(11, 11) type mismatch;
found : A$A562.this.Item
required: akka.http.scaladsl.marshalling.ToResponseMarshallable
complete(item);}
^
导入有何影响?
答案 0 :(得分:2)
执行RequestContext#complete(response)
时,ToResponseMarshallable
作为输入。
package akka.http.scaladsl.server
@InternalApi
private[http] class RequestContextImpl(
override def complete(trm: ToResponseMarshallable): Future[RouteResult] =
trm(request)(executionContext)
.fast.map(res ⇒ RouteResult.Complete(res))(executionContext)
.fast.recover {
case Marshal.UnacceptableResponseContentTypeException(supported) ⇒
RouteResult.Rejected(UnacceptedResponseContentTypeRejection(supported) :: Nil)
case RejectionError(rej) ⇒
RouteResult.Rejected(rej :: Nil)
}(executionContext)
}
SprayJsonSupport
是定义隐式Marshallers
的对象,它们是Marshallable
package akka.http.scaladsl.marshallers.sprayjson
trait SprayJsonSupport {
implicit def sprayJsonMarshallerConverter[T](writer: RootJsonWriter[T])(implicit printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[T] =
sprayJsonMarshaller[T](writer, printer)
implicit def sprayJsonMarshaller[T](implicit writer: RootJsonWriter[T], printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[T] =
sprayJsValueMarshaller compose writer.write
implicit def sprayJsValueMarshaller(implicit printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[JsValue] =
Marshaller.StringMarshaller.wrap(MediaTypes.`application/json`)(printer)
}
如果您没有导入SprayJsonSupport
,则无法隐式Marshallers
将您的案例类编组为所需的输出JSObject
。
如果您不想导入提供默认为JsonMarshallers的SprayJsonSupport
,请编写您自己的,或复制粘贴来自JsonSpraySupport
的marshallers。
例如
object GetHttpRoutes {
case class Acknowledge(status: String)
implicit val itemFormat = jsonFormat1(Acknowledge)
implicit def toJsonMarshallerConverter[Entity](writer: RootJsonWriter[Entity])(implicit printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[Entity] =
toJsonMarshaller[Entity](writer, printer)
implicit def toJsonMarshaller[Entity](implicit writer: RootJsonWriter[Entity], printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[Entity] =
toJsValueMarshaller compose writer.write
implicit def toJsValueMarshaller(implicit printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[JsValue] =
Marshaller.StringMarshaller.wrap(MediaTypes.`application/json`)(printer)
val get_api =
path("") {
get { context =>
context.complete {
Acknowledge(status = "xbox")
}
}
}
}
trait HTTPRoutes {
implicit val system: ActorSystem
implicit val materializer: ActorMaterializer
val route = GetHttpRoutes.get_api
}
<强>测试强>
class GetHttpRoutesCompSpecs extends WordSpec with Matchers with ScalatestRouteTest with BeforeAndAfterAll {
"HTTP GET endpoints" should {
"returns xbox on /" in {
Get("/") ~> GetHttpRoutes.get_api ~> check {
responseAs[String] shouldEqual """{"status":"xbox"}"""
}
}
}
}