Skip to content

Marshalling and Unmarshalling

agaoglu edited this page Dec 15, 2011 · 10 revisions

HTTP requests and responses can have an "entity body", which can be text or binary content. However, when consuming requests and producing responses in your application you normally want to work with your domain objects rather than low level representations in XML, JSON or other serialization formats.

spray supports decoupling your application logic from these serialization concerns by separating out marshalling (converting domain objects to a serialized format) and unmarshalling (creating domain objects from a serialized format).

Suppose your application provides actions upon Person resources, which are represented in your code like this:

case class Person(name: string, firstname: String, age: int)

A part of your spray service might be defined like this:

path("person" / IntNumber) { id =>
  get { ctx =>
    val person: Person = ... // load Person from the DB using the id
    ctx.complete(person) // uses the in-scope Marshaller to convert the
                       // Person into a format accepted by the client
  } ~
  put {
    content(as[Person]) { person =>
      ... // operate directly on the Person object,
          // e.g. write it to the database                          
    }
  }
}

Marshalling

When you use the RequestContext complete method with an argument of a custom type the Scala compiler will look for an in-scope implicit Marshaller for your type to do the job of converting your custom object to a representation accepted by the client. spray comes with the following marshallers already defined (as implicit objects in the DefaultMarshallers trait):

  • String to media type text/plain
  • Array[Char] to media type text/plain
  • NodeSeq to text/xml, text/html or application/xhtml+xml
  • FormData to application/x-www-form-urlencoded
  • MultipartFormData to multipart/form-data
  • Any type T to application/json

The last marshaller is only available, when you pull in the dependency on spray-json, mix in the SprayJsonSupport trait (or import cc.spray.typeconversion.SprayJsonSupport._) and supply a spray-json JsonFormat for your type T (see the documentation for spray-json how to easily get this done).

Creating your own marshallers for custom types is also not hard at all. For guidance take a look at the implementation of the built-in marshallers in DefaultMarshallers trait.

Unmarshalling

The opposite of marshalling is unmarshalling, i.e. the creation of custom objects from XML, JSON and the like. This job is done by Unmarshaller instances, which just like Marshaller instances, are really easy to write for your custom types and need to be available implicitly. spray comes with the following unmarshallers already defined (as implicit vals in the DefaultUnmarshallers trait):

  • Media type text/plain to String
  • Media type text/plain to Array[Char]
  • text/xml, text/html or application/xhtml+xml to NodeSeq
  • application/x-www-form-urlencoded to FormData
  • multipart/form-data to MultipartFormData
  • application/json to any type T

Just like in the case of marshallers the last conversion is only available, when you pull in the dependency on spray-json, mix in the SprayJsonSupport trait (or import cc.spray.typeconversion.SprayJsonSupport._) and supply a spray-json JsonFormat for your type T (see the documentation for spray-json how to easily get this done).

Clone this wiki locally