Marshalling

TODO overhaul for Java

Marshalling is the process of converting a higher-level (object) structure into some kind of lower-level representation, often a “wire format”. Other popular names for marshalling are “serialization” or “pickling”.

In Akka HTTP, marshalling means the conversion of an object of type T into a lower-level target type, e.g. a MessageEntity (which forms the “entity body” of an HTTP request or response) or a full HttpRequest or HttpResponse.

On the server-side, for example, marshalling is used to convert an application-domain object to a response entity. Requests can contain an Accept header that lists acceptable content types for the client, such as application/json and application/xml. A marshaller contains the logic to negotiate the result content types based on the Accept and the AcceptCharset headers.

Basic Design

Marshalling of instances of type A into instances of type B is performed by a Marshaller<A, B>.

Contrary to what you might initially expect, Marshaller<A, B> is not a plain function A => B but rather essentially a function A => CompletionStage<List<Marshalling<B>>>. Let’s dissect this rather complicated looking signature piece by piece to understand why marshallers are designed this way. Given an instance of type A a Marshaller<A, B> produces:

  1. A CompletionStage: This is probably quite clear. Marshallers are not required to synchronously produce a result, so instead they return a future, which allows for asynchronicity in the marshalling process.

  2. of List: Rather than only a single target representation for A marshallers can offer several ones. Which one will be rendered onto the wire in the end is decided by content negotiation. For example, the Marshaller<OrderConfirmation, MessageEntity> might offer a JSON as well as an XML representation. The client can decide through the addition of an Accept request header which one is preferred. If the client doesn’t express a preference the first representation is picked.

  3. of Marshalling<B>: Rather than returning an instance of B directly marshallers first produce a Marshalling<B>. This allows for querying the MediaType and potentially the HttpCharset that the marshaller will produce before the actual marshalling is triggered. Apart from enabling content negotiation this design allows for delaying the actual construction of the marshalling target instance to the very last moment when it is really needed.

Predefined Marshallers

Akka HTTP already predefines a number of marshallers for the most common types. Specifically these are:

All marshallers can be found in Marshaller.

Custom Marshallers

Akka HTTP gives you a few convenience tools for constructing marshallers for your own types. Before you do that you need to think about what kind of marshaller you want to create. If all your marshaller needs to produce is a MessageEntity then you should probably provide a Marshaller<T, MessageEntity>. The advantage here is that it will work on both the client- as well as the server-side since a Marshaller<T, HttpResponse> as well as a Marshaller<T, HttpRequest> can automatically be created if a Marshaller<T, MessageEntity> is available.

If, however, your marshaller also needs to set things like the response status code, the request method, the request URI or any headers then a Marshaller<T, MessageEntity> won’t work. You’ll need to fall down to providing a Marshaller<T, HttpResponse> or a Marshaller<T, HttpRequest> directly.

For writing your own marshallers you won’t have to “manually” implement the Marshaller class directly.

Deriving Marshallers

Sometimes you can save yourself some work by reusing existing marshallers for your custom ones. The idea is to “wrap” an existing marshaller with some logic to “re-target” it to your type.

In this regard wrapping a marshaller can mean one or both of the following two things:

  • Transform the input before it reaches the wrapped marshaller
  • Transform the output of the wrapped marshaller

For the latter (transforming the output) you can use baseMarshaller.map, which works exactly as it does for functions. For the former (transforming the input) you have four alternatives:

  • baseMarshaller.compose
  • baseMarshaller.composeWithEC
  • baseMarshaller.wrap
  • baseMarshaller.wrapWithEC

compose works just like it does for functions. wrap is a compose that allows you to also change the ContentType that the marshaller marshals to. The ...WithEC variants allow you to receive an ExecutionContext internally if you need one, without having to depend on one being available implicitly at the usage site.

Using Marshallers

In many places throughout Akka HTTP, marshallers are used implicitly, e.g. when you define how to complete a request using the Routing DSL.

However, many directives dealing with marshalling also require that you pass a marshaller explicitly. The following example shows how to marshal Java bean classes to JSON using the Jackson JSON support:

sourceimport akka.http.javadsl.marshallers.jackson.Jackson;
import akka.http.javadsl.model.StatusCodes;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import static akka.http.javadsl.server.Directives.*;
import static akka.http.javadsl.unmarshalling.StringUnmarshallers.INTEGER;

private static Route putPetHandler(Map<Integer, Pet> pets, Pet thePet) {
    pets.put(thePet.getId(), thePet);
    return complete(StatusCodes.OK, thePet, Jackson.<Pet>marshaller());
}

private static Route alternativeFuturePutPetHandler(Map<Integer, Pet> pets, Pet thePet) {
    pets.put(thePet.getId(), thePet);
  CompletableFuture<Pet> futurePet = CompletableFuture.supplyAsync(() -> thePet);
    return completeOKWithFuture(futurePet, Jackson.<Pet>marshaller());
}
Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.