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