Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Marshalling Unmarshalling

Johannes Rudolph edited this page Aug 14, 2013 · 6 revisions

. . . Deprecation Note

This documentation is for release 0.9.0 (from 03/2012), which is built against Scala 2.9.1 and Akka 1.3.1 (see Requirements for more information). Most likely, this is not the place you want to look for information. Please turn to the main spray site at http://spray.io for more information about other available versions.

. . .

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.

Marshalling

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.

handleWith

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.