Custom (un)Marshalling with the Camel Rest DSL

Sometimes you want to use a custom marshaller to marshal or unmarshal your messages. In our case we needed to parse all date fields to a specific format when marshalling our output message. We noticed that we could set a custom jsonDataFormat or a custom xmlDataFormat. These options allow you to specify your own DataFormat class, in essence your customized marshaller.

We needed to send out XML or JSON, depending on the clients request (http header: Accept). Because you implement the same interface I will show only the JSON DataFormat. The dataFormat options expects a class that implements the “org.apache.camel.spi.DataFormat” interface. The interface defines two methods, marshal and unmarshal. When you only use the DataFormat for outgoing messages implementing the marshal method is sufficient.

public class JsonDataFormat implements DataFormat {

    private final ObjectMapper jacksonMapper;

    public JsonDataFormat() {
        jacksonMapper = new ObjectMapper();
    }

    @Override
    public void marshal(Exchange exchange, Object obj, OutputStream stream) throws Exception {

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss");
        jacksonMapper.setDateFormat(dateFormat);

        if (view != null) {
            ObjectWriter w = jacksonMapper.writerWithView(view);
            w.writeValue(stream, obj);
        } else {
            stream.write(jacksonMapper.writeValueAsBytes(obj));
        }
    }

    @Override
    public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
        return null;
    }

Now you cannot simply add the class as a bean and refer to it. You need to add it as a DataFormat to the camel context. This can be done by adding the following file to your META-INF directory: in the classpath: services.org.apache.camel.dataformat add a file which contains the following line:

class=nl.janssen.dataformats.JsonDataFormat

The last thing you need to do is tell your restConfiguration that you want to use your dataFormat. When setting the dataFormat you have to use the file name you specified in the above mentioned classpath. In my case JsonFormat.

restConfiguration()
      .component("jetty")
      .host("0.0.0.0")
      .port("8080")
      .bindingMode(RestBindingMode.auto)
      .xmlDataFormat("XmlFormat")
      .jsonDataFormat("JsonFormat");

If you want a custom xmlDataFormat you simply have to implement the DataFormat interface again but now with an XML (un)marshalling implementation.