The akka-http 2.4.7 reference states that it's possible to do custom Deserializers to convert query parameters, without storing them in an intermediate variable:
"amount".as[Int]extract value of parameter "amount" as Int, you need a matching Deserializer in scope for that to work (see also Unmarshalling)
"amount".as(deserializer)extract value of parameter "amount" with an explicit Deserializer
However, the Deserialized parameter sample on that page does not show how custom deserializers are being used.
How do I define one, so that I can say, e.g. .as[MyType]?
I think the documentation is at fault, because I cannot find a Deserializer mentioned anywhere in akka sources: search

Screenshot on how Deserializer is typeset in the Akka docs.
A Deserializer is just a name for an Unmarshaller in akka-http 2.4.7 (same for akka-http 2.4.8)
Edit: Let's say you're extracting a query parameter named type, and you want a Deserializer that can pattern-match that type parameter from a String to a MyType.
Your route that's in your server app may look like this:
object MyServer {
  ...
  // Assuming that you're requiring a
  // `type` parameter from a `POST` request
  import MyType._
  val route =
    post {
      parameter('type.as(myTypeDeserializer)) { myTypeValue =>
        complete {
          // `myTypeValue` is already pattern-matched
          // to type `MyType` here thanks to `myTypeDeserializer`
          ...
        }
      }
    }
  ...
}
Your MyType object may look like this:
object MyType {
  case object Type1 extends MyType
  case object Type2 extends MyType
  case object Type3 extends MyType
  import akka.http.scaladsl.unmarshalling.Unmarshaller
  // Here we pattern match the query parameter,
  // which has type `String`, to a `MyType`
  val stringToMyType = Unmarshaller.strict[String, MyType] {
    case "type1" => MyType.Type1
    case "type2" => MyType.Type2
    case "type3" => MyType.Type3
  }
}
Hence akka-http will automatically throw a BadRequest response if user requests an unsupported type parameter.
I was able to declare the custom query parameter marshaller right, based on the PredefinedFromStringUnmarshallers.scala built-in samples.
implicit val desId: Unmarshaller[String,Context.Id] = Unmarshaller.strict[String, Context.Id] { s =>
  Context.Id.parseOpt(s).getOrElse(
    if (s=="") throw Unmarshaller.NoContentException
    else throw new IllegalArgumentException( s"Not a valid id: '$s'" )
  )
}
Providing the return type explicitly seems to matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With