XML Support

Akka HTTP’s marshalling and unmarshalling infrastructure makes it rather easy to seamlessly support specific wire representations of your data objects, like JSON, XML or even binary encodings.

Akka HTTP does not currently provide a Java API for XML support. If you need to produce and consume XML, you can write a custom marshaller using Jackson, which is also the library used for providing JSON support.

import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import akka.http.javadsl.model.*;
import akka.http.javadsl.marshalling.Marshaller;
import akka.http.javadsl.unmarshalling.Unmarshaller;

public class JacksonXmlSupport {
  private static final ObjectMapper DEFAULT_XML_MAPPER =
    new XmlMapper().enable(SerializationFeature.WRAP_ROOT_VALUE);
  private static final List<MediaType> XML_MEDIA_TYPES = Arrays.asList(MediaTypes.APPLICATION_XML, MediaTypes.TEXT_XML);

  public static <T> Marshaller<T, RequestEntity> marshaller() {
    return Marshaller.wrapEntity(
      u -> toXML(DEFAULT_XML_MAPPER, u),
      Marshaller.stringToEntity(),
      MediaTypes.APPLICATION_XML
    );
  }

  public static <T> Unmarshaller<HttpEntity, T> unmarshaller(Class<T> expectedType) {
    return Unmarshaller.forMediaTypes(XML_MEDIA_TYPES, Unmarshaller.entityToString())
                       .thenApply(xml -> fromXML(DEFAULT_XML_MAPPER, xml, expectedType));
  }

  private static <T> String toXML(ObjectMapper mapper, T object) {
    try {
      return mapper.writeValueAsString(object);
    } catch (IOException e) {
      throw new IllegalArgumentException("Cannot marshal to XML: " + object, e);
    }
  }

  private static <T> T fromXML(ObjectMapper mapper, String xml, Class<T> expectedType) {
    try {
      return mapper.readerFor(expectedType).readValue(xml);
    } catch (IOException e) {
      throw new IllegalArgumentException("Cannot unmarshal XML as " + expectedType.getSimpleName(), e);
    }
  }
}

The custom XML (un)marshalling code shown above requires that you depend on the jackson-dataformat-xml library.

sbt
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.8"
Gradle
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.8.8'
Maven
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.8.8</version>
</dependency>

For XML Akka HTTP currently provides support for Scala XML right out of the box through it’s akka-http-xml module.

Scala XML Support

The ScalaXmlSupport trait provides a FromEntityUnmarshaller[NodeSeq] and ToEntityMarshaller[NodeSeq] that you can use directly or build upon.

In order to enable support for (un)marshalling from and to XML with Scala XML NodeSeq you must add the following dependency:

sbt
"com.typesafe.akka" %% "akka-http-xml" % "10.0.10" 
Gradle
compile group: 'com.typesafe.akka', name: 'akka-http-xml_2.12', version: '10.0.10'
Maven
<dependency>
  <groupId>com.typesafe.akka</groupId>
  <artifactId>akka-http-xml_2.12</artifactId>
  <version>10.0.10</version>
</dependency>

Once you have done this (un)marshalling between XML and NodeSeq instances should work nicely and transparently, by either using import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ or mixing in the akka.http.scaladsl.marshallers.xml.ScalaXmlSupport trait.

The source code for this page can be found here.