web-dev-qa-db-ja.com

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では異なりますか?

stringUnmarshallerを持つakka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallersをインポートしようとしましたが、役に立ちません。おそらく、これはFromEntityUnmarshaller[String]ではなくタイプFromRequestUnmarshaller[String]を返すためです。 spray.httpx.unmarshalling.BasicUnmarshallersには文字列unmarshallerもありますが、これも役に立ちません。akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallersも役に立ちません。

どうすれば文字列にマーシャル解除(およびマーシャル)できますか?

(ボーナス:JsObjectで直接アンマーシャルする方法(jsonを再生します)。ただし、これが機能しない理由に興味があり、他の場合に役立つ可能性があるため、文字列のみ)。

1.0-RC3を使用

ありがとう。

13
Ixx

スコープに適切な暗黙があれば、コードは問題ないはずです。スコープに暗黙の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)
  }    
}
17
cmbaxter