#scala #spray
#scala #спрей
Вопрос:
В scala spray есть ли способ преобразовать из a Unmarshaller[T]
в a FromRequestUnmarshaller[T]
. Я застрял, пытаясь заставить entity
директиву работать без использования implicits. Например:
...
} ~ post {
path("myPath") {
entity(sprayJsonUnmarshaller[MyCaseClass](myCaseClassRootJsonFormat)) { myCaseClass =>
complete { handle(myCaseClass) }
}
} ~ ...
Ошибка компилятора:
Multiple markers at this line
- type mismatch; found : spray.httpx.unmarshalling.Unmarshaller[MyCaseClass] (which
expands to) spray.httpx.unmarshalling.Deserializer[spray.http.HttpEntity,MyCaseClass]
required: spray.httpx.unmarshalling.FromRequestUnmarshaller[?] (which expands to)
spray.httpx.unmarshalling.Deserializer[spray.http.HttpRequest,?]
- type mismatch; found : spray.httpx.unmarshalling.Unmarshaller[MyCaseClass] (which
expands to) spray.httpx.unmarshalling.Deserializer[spray.http.HttpEntity,MyCaseClass]
required: spray.httpx.unmarshalling.FromRequestUnmarshaller[?] (which expands to)
spray.httpx.unmarshalling.Deserializer[spray.http.HttpRequest,?]
Ответ №1:
В этой части Spray сильно зависит от неявного разрешения. Возможно, я ошибаюсь, но, насколько я знаю, теперь есть простой и элегантный способ сделать это. Как и было задумано, вы должны выполнить следующую директиву: entity(as[MyCaseClass])
. Затем, если вы посмотрите на as[_]
директиву, нет короткого способа сделать простой unmarshaller (который принимает сущность и создает ваш класс case) в fromRequestUnmarshaller (из HttpRequest -> case class ), все неявные расширители можно найти [здесь] (https://github.com/spray/spray/blob/master/spray-httpx/src/main/scala/spray/httpx/unmarshalling/UnmarshallerLifting.scala#L21). Поэтому, когда вы вызываете entity(as[MyCaseClass])
, он расширяется до этого:
entity {
as[MyCaseClass] {
fromRequestUnmarshaller[MyCaseClass] {
fromMessageUnmarshaller[MyCaseClass] {
sprayJsonUnmarshaller[MyCaseClass](myCaseClassRootJsonFormat)
}
}
}
}
Если вы хотите сделать его явным, вам следует записать его в верхней форме. Таким образом, вы можете удалить as[MyCaseClass]
С другой стороны, вы можете выбрать другой явный способ — извлечь объект и преобразовать его в json:
requestInstance { req =>
val json = req.entity.asString.parseJson
json.convertTo(myCaseClassRootJsonFormat)
}
Комментарии:
1. Я также сделал
FromRequestUnmarshaller
следующее:def unmarshaller[T](fmt: JsonFormat[T]): FromRequestUnmarshaller[T] = { val f: HttpRequest => T = hr => fmt.read(hr.entity.asString) Deserializer.fromFunction2Converter[HttpRequest, T](f) }