Подтвердить что ты не робот

Как отключить объект запроса akka http как строку?

Я пытаюсь развязать запрос полезной нагрузкой как строку, но по какой-то причине она терпит неудачу. Мой код:

path("mypath") {

  post {
    decodeRequest {
      entity(as[String]) {jsonStr => //could not find implicit value for...FromRequestUnmarshaller[String]
        complete {
          val json: JsObject = Json.parse(jsonStr).as[JsObject]
          val jsObjectFuture: Future[JsObject] = MyDatabase.addListItem(json)
          jsObjectFuture.map(_.as[String])
        }
      }          
    }
  }
}

В этом SO-потоке, например, кажется, что это неявное должно быть доступно по умолчанию. Но может быть, это отличается от akka-http?

Я попытался импортировать akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers, у которого есть stringUnmarshaller, но это не помогает. Возможно, потому что это возвращает тип FromEntityUnmarshaller[String] not FromRequestUnmarshaller[String]. Там также строка unmarshaller в spray.httpx.unmarshalling.BasicUnmarshallers, но это также не помогает, ни akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers

Как я могу отменить (и маршалл) в строку?

(Бонус: как размонтировать непосредственно в JsObject (play json). Но также только строка, поскольку меня интересует, почему это не работает, и может быть полезно для других случаев).

Использование 1.0-RC3

Спасибо.

4b9b3361

Ответ 1

Ваш код должен быть в порядке, если у вас есть правильные импликации в сфере видимости. Если у вас есть неявный FlowMaterializer в области видимости, тогда все должно работать так, как ожидалось, поскольку этот код, который компилирует, показывает:

import akka.http.scaladsl.server.Route
import akka.actor.ActorSystem
import akka.stream.ActorFlowMaterializer
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.stream.FlowMaterializer

implicit val system = ActorSystem("test")
implicit val mater = ActorFlowMaterializer()

val routes:Route = {
  post{
    decodeRequest{
      entity(as[String]){ str =>
        complete(OK, str) 
      }
    }
  }    
}

Если вы хотите сделать что-то еще дальше и отменить маркер в JsObject, вам просто понадобится неявная Unmarshaller в области для обработки этого преобразования, что-то вроде этого:

implicit val system = ActorSystem("test")
implicit val mater = ActorFlowMaterializer()

import akka.http.scaladsl.unmarshalling.Unmarshaller
import akka.http.scaladsl.model.HttpEntity

implicit val um:Unmarshaller[HttpEntity, JsObject] = {
  Unmarshaller.byteStringUnmarshaller.mapWithCharset { (data, charset) =>
    Json.parse(data.toArray).as[JsObject]
  }    
}  

val routes:Route = {
  post{
    decodeRequest{
      entity(as[String]){ str =>
        complete(OK, str) 
      }
    }
  } ~
  (post & path("/foo/baz") & entity(as[JsObject])){ baz =>
    complete(OK, baz.toString)
  }    
}