-
Notifications
You must be signed in to change notification settings - Fork 0
Marshalling Unmarshalling
There are a few directives that allow for the easy integration of marshalling and unmarshalling logic (as discussed in
the chapter about Marshalling and Unmarshalling) into your route structure. The most important one is probably the
content directive, which takes an Unmarshaller as parameter and uses it for extracting the requests entity body as a
custom type.
This is how you use it:
case class Person(name: string, firstname: String, age: int)
post {
content(as[Person]) { person =>
... // person is an instance of Person
}
}This code will only compile if there is an Unmarshaller for Persons implicitly available at the call site of the
content directive. The Unmarshaller will convert the request content if it has a media type that is supported by the
Unmarshaller. If the request has a non-supported media type the content directive will reject the request with an
UnsupportedRequestContentTypeRejection, which will trigger a 415 Unsupported Media Type error response by default.
If your application supports requests with an optional rather than a mandatory entity body simply use
content(as[Option[T]]). If there is an Unmarshaller for T in scope spray will automatically construct one for
Option[T] without any further required action on your part. Note that this still requires content to be
well-formed if present. If the Unmarshaller cannot properly convert the entity body for some reason the directive will
reject the request with a MalformedRequestContentRejection, which triggers a 400 Bad Request error response by
default.
Most of the time marshalling custom objects does not require special directive support as the complete method of the
RequestContext directly allows custom objects as argument, if there is a Marshaller for their type implicitly
available. However, sometimes you might want to decouple Marshaller resolution from the actual request completion.
This can be achieved via the produce directive, which takes a Marshaller as argument.
You can use it as follows:
get {
produce(instanceOf[Person]) { personCompleter =>
databaseActor ! ShowPersonJob(personCompleter)
}
}The produce directive in this example extracts a function Person => Unit that you can use to complete the request.
You could for example ship the completer function off to another actor, which does not need to know anything about
"Marshallers" and still has a way of completing the request directly with a Person instance.
As an added convenience spray also comes with the handleWith directive, which combines content and produce.
This is its implementation:
/**
* Returns a Route that completes the request using the given function. The input to the function is produced with
* the in-scope unmarshaller and the result value of the function is marshalled with the in-scope marshaller.
*/
def handleWith[A :Unmarshaller, B: Marshaller](f: A => B): Route = {
(content(as[A]) & produce(instanceOf[B])) { (a, p) =>
_ => p(f(a))
}
}Note that the handleWith directive does not take an inner route and can therefore not be combined with other
directives via the & and | operators.
- Home
- Requirements
- spray-server
- ... Getting Started
- ... Key Concepts
- ...... Request Lifecycle
- ...... Routes
- ...... Directives
- ...... Composing Directives
- ...... Rejections
- ...... Marshalling and Unmarshalling
- ... Predefined Directives
- ...... Method Filters
- ...... Path Filters
- ...... Parameter Filters
- ...... Form-Field Filters
- ...... Marshalling/Unmarshalling
- ...... Caching
- ...... Detach
- ...... Encoding/Decoding
- ...... Authentication/Authorization
- ...... File and Resource Directives
- ...... Misc Directives
- ... Advanced Topics
- ...... Case Class Extraction
- ...... Custom Directives
- ...... Custom Media Types
- ...... Custom Error Responses
- ... Configuration
- ... Testing
- ... Example Projects
- spray-client
- Patch Policy
- Credits
- Sponsors