Scala Akka HTTP casting parameter as java.time.ZonedDateTime

人走茶凉 提交于 2019-12-01 11:59:21

问题


I'm working on a REST service using Akka HTTP (in Scala). I would like a parameter that is passed in to a http get request to be converted to the ZonedDateTime type. The code works fine if I try to use String or Int but fails with a ZonedDateTime type. The code would look like so:

parameters('testparam.as[ZonedDateTime])

Here is the error that I'm seeing:

Error:(23, 35) type mismatch;
 found   : akka.http.scaladsl.common.NameReceptacle[java.time.ZonedDateTime]
 required: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet
          parameters('testparam.as[ZonedDateTime]){

If I add more than one parameter to the list I get a different error:

Error:(23, 21) too many arguments for method parameters: (pdm: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet)pdm.Out
          parameters('testparam.as[ZonedDateTime], 'testp2){

I found this in the documentation when I was researching the problem http://doc.akka.io/japi/akka-stream-and-http-experimental/2.0/akka/http/scaladsl/server/directives/ParameterDirectives.html and I tried the workaround of adding import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet along with using Scala 2.11 but the problem persisted.

Could someone please explain what I'm doing wrong and why the ZonedDateTime type doesn't work? Thanks in advance!

Here is a code snippet that should reproduce the problem I'm seeing

import java.time.ZonedDateTime

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer

import scala.io.StdIn


object WebServer {
  def main(args: Array[String]) {

    implicit val system = ActorSystem("my-system")
    implicit val materializer = ActorMaterializer()
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.dispatcher

    val route =
      path("hello") {
        get {
          parameters('testparam.as[ZonedDateTime]){
            (testparam) =>
              complete(testparam.toString)
          }
        }
      }

    val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)

    println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
    StdIn.readLine() // let it run until user presses return
    bindingFuture
      .flatMap(_.unbind()) // trigger unbinding from the port
      .onComplete(_ => system.terminate()) // and shutdown when done
  }
}

回答1:


As ZonedDateTime is not natively unmarshalled by Akka-HTTP, you will need to provide a custom unmarshaller to the parameters directive.

This functionality is briefly described in the docs here.

Your unmarshaller can be created from a function by using Unmarshaller.strict, e.g.

  val stringToZonedDateTime = Unmarshaller.strict[String, ZonedDateTime](ZonedDateTime.parse)

This example assumes your param is provided in an ISO format. If it's not, you'll need to amend the unmarshalling function.

You can then use the unmarshaller passing it to the parameters directive:

parameters("testparam".as(stringToZonedDateTime)){
            (testparam) =>
              complete(testparam.toString)
          }


来源:https://stackoverflow.com/questions/45383102/scala-akka-http-casting-parameter-as-java-time-zoneddatetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!