我有Java背景,但我现在正在学习Scala与Spray一起使用。在查看其中一个示例程序时,我遇到了这种方法:
/**
* Marshals instances of ``Either[A, B]`` into appropriate HTTP responses by marshalling the values
* in the left or right projections; and by selecting the appropriate HTTP status code for the
* values in the left projection.
*
* @param ma marshaller for the left projection
* @param mb marshaller for the right projection
* @param esa the selector converting the left projection to HTTP status code
* @tparam A the left projection
* @tparam B the right projection
* @return marshaller
*/
implicit def errorSelectingEitherMarshaller[A, B](implicit ma: Marshaller[A],
mb: Marshaller[B], esa: ErrorSelector[A]): Marshaller[Either[A, B]] =
Marshaller[Either[A, B]] { (value, ctx) =>
value match {
case Left(a) =>
val mc = new CollectingMarshallingContext()
ma(a, mc)
ctx.handleError(ErrorResponseException(esa(a), mc.entity))
case Right(b) =>
mb(b, ctx)
}
}
(value, ctx)
对我来说没有意义。这些似乎是参数,但我不知道如何传入任何内容。就我所知,其他任何地方都没有定义值或ctx。这种方法应该如何工作?
可以通过在Typesafe Activator中键入activator-akka-spray并查看src / main / scala / api / DefaultJsonFormats.scala来找到该示例。 (显示的文件here包含方法,但文件的其余部分不相同)以下是全班:
package api
import spray.json._
import java.util.UUID
import scala.reflect.ClassTag
import spray.httpx.marshalling.{MetaMarshallers, Marshaller, CollectingMarshallingContext}
import spray.http.StatusCode
import spray.httpx.SprayJsonSupport
/**
* Contains useful JSON formats: ``j.u.Date``, ``j.u.UUID`` and others; it is useful
* when creating traits that contain the ``JsonReader`` and ``JsonWriter`` instances
* for types that contain ``Date``s, ``UUID``s and such like.
*/
trait DefaultJsonFormats extends DefaultJsonProtocol with SprayJsonSupport with MetaMarshallers {
/**
* Computes ``RootJsonFormat`` for type ``A`` if ``A`` is object
*/
def jsonObjectFormat[A : ClassTag]: RootJsonFormat[A] = new RootJsonFormat[A] {
val ct = implicitly[ClassTag[A]]
def write(obj: A): JsValue = JsObject("value" -> JsString(ct.runtimeClass.getSimpleName))
def read(json: JsValue): A = ct.runtimeClass.newInstance().asInstanceOf[A]
}
/**
* Instance of the ``RootJsonFormat`` for the ``j.u.UUID``
*/
implicit object UuidJsonFormat extends RootJsonFormat[UUID] {
def write(x: UUID) = JsString(x.toString)
def read(value: JsValue) = value match {
case JsString(x) => UUID.fromString(x)
case x => deserializationError("Expected UUID as JsString, but got " + x)
}
}
/**
* Type alias for function that converts ``A`` to some ``StatusCode``
* @tparam A the type of the input values
*/
type ErrorSelector[A] = A => StatusCode
/**
* Marshals instances of ``Either[A, B]`` into appropriate HTTP responses by marshalling the values
* in the left or right projections; and by selecting the appropriate HTTP status code for the
* values in the left projection.
*
* @param ma marshaller for the left projection
* @param mb marshaller for the right projection
* @param esa the selector converting the left projection to HTTP status code
* @tparam A the left projection
* @tparam B the right projection
* @return marshaller
*/
implicit def errorSelectingEitherMarshaller[A, B](implicit ma: Marshaller[A], mb: Marshaller[B], esa: ErrorSelector[A]): Marshaller[Either[A, B]] =
Marshaller[Either[A, B]] { (value, ctx) =>
value match {
case Left(a) =>
val mc = new CollectingMarshallingContext()
ma(a, mc)
ctx.handleError(ErrorResponseException(esa(a), mc.entity))
case Right(b) =>
mb(b, ctx)
}
}
}
答案 0 :(得分:1)
通过喷射隐式调用编组来进行编组。 Spray将提供要编组的值以及请求上下文。