Muster by json4s

Fast serialization for classes in scala

Custom serializers

Muster works with a system of type classes and a custom deserializer is an implementation of a muster.input.Consumer[T] trait. Similarly custom serializers are an implementtation of a muster.output.Producer[T] trait.

If you want to learn more about the internals of muster, check out the extending muster doc.

The functionality described on this page is provided by muster-core. You can get muster-core from maven central. Check the releases page for the latest version.

libraryDependencies += "org.json4s" %% "muster-core" % "latest"


A deserializer is an implementation of muster.output.Producer[T]

import muster._

trait Producer[T] {
  def produce(value: T, formatter: OutputFormatter[_])

In this case the formatter property provides a mechanism for rendering the provided value. As an example lets define a custom serializer for a person case class.

import muster._

case class Address(firstLine: String, secondLine: Option[String], postcode: String, state: String, country: String)
case class Person(id: Int, name: String, addresses: Seq[Address])

implicit object PersonProducer extends Producer[Person] {
  def produce(value: Person, formatter: OutputFormatter[_]) {



    val arrProducer = implicitly[Producer[Seq[Address]]]
    arrProducer.produce(value.addresses, formatter)


For this example writing the id and name property are pretty straightforward. And by implicitly resolving the undefined address producer the compiler will generate a version of a Producer[Address] that would do the exact same thing as in the example for the name property.

The macro for the Seq producer generates code that looks like this:

value.addresses foreach (implicitly[Producer[Address]].produce(_, formatter))


A serializer is an implementation of muster.Consumer[T]

import muster._

trait Consumer[S] {
  def consume(node: AstNode[_]): S

In this case we get an ast node representation as node and we need to turn it into type S. As an example we'll provide a custom deserializer for the person case class

import muster._

implicit object PersonConsumer extends Consumer[Person] {
  def consume(node: AstNode[_]): Person = node match {
    case obj: ObjectNode => 
      val addressesConsumer = implicitly[Consumer[Seq[Address]]]
    case n => throw new MappingException(s"Can't convert a ${n.getClass} to a Person")

This example makes use of the shortest notation for writing a custom deserializer. First the addresses consumer is implictly resolved, like in the serializer example, this will get a version of Seq[Consumer[Address]] generated by the compiler. Then reading the fields is relatively straight forward.

The code the macro generates for the extraction of the Seq kind of looks like this:

node match {
  case arr: ArrayNode =>
    val addresses = Seq.newBuilder[Address]
    val addressesConsumer = implicitly[Consumer[Address]]
    while(arr.hasNextNode) {
      addresses += addressesConsumer.consume(arr.readObject())
  case n => throw new MappingException("Can't read array from ${n.getClass}")