Enumerations

christophercurrie edited this page Apr 11, 2013 · 2 revisions
Clone this wiki locally

Introduced in Jackson Scala Module 2.2

Enumerations in Scala can be tricky. The Scala documentation recommends declaring them in the form:

object Weekday extends Enumeration {
  type Weekday = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

This has two challenges to overcome:

  1. Enumeration values have the Scala type of Weekday#Value, since Value is an instance-scoped abstract class. However, JVM erasure reduces all of these to the same runtime type, and the type of the enclosing class is lost.

  2. Scala does not allow code to access the class of the singleton object instance at compile time; classOf[Weekday.type] does not compile. Type tricks have to be employed to construct a compile-time proxy.

Thankfully, you can refer to an object's type as a type parameter, so to handle this we rely on the TypeReference class used in Jackson core. The difference is that normally you can create an anonymous derived class at runtime, but because an annotation needs a compile-type constant, we must create a named derived class to stand-in for the enumeration type Scala doesn't allow us to name:

class WeekdayType extends TypeReference[Weekday.type]
case class WeekdayHolder(@JsonScalaEnumeration(classOf[WeekdayType]) weekday: Weekday.Weekday)

The first line declares our TypeReference proxy, to give the compiler a class it can refer to. The second line refers to the class instance in the new @JsonScalaEnumeration annotation, to provide the information the Jackson Scala Module needs to locate the withName method required to instantiate the enumeration value.

Backward compatibility

Versions of Jackson prior to 2.2 used a different serialization format for Enumerations that did not require an annotation. If the @JsonScalaEnumeration is omitted, the serialized form of the above will look like

{"weekday":{"enumClass":"Weekday","value":"Fri"}}

The enumClass field carries the necessary type information in the serialized form. It is expected this behavior will be deprecated in version 2.3, and removed entirely in 3.0.