-
Notifications
You must be signed in to change notification settings - Fork 0
Annotations
Salat offers the following annotations to customize serialization behavior:
-
@Salatto support polymorphic instances of a trait or abstract superclass -
@Keyto change the name of a field -
@Persistto serialize a value outside the case class constructor -
@Ignoreto ignore a field in the case class constructor -
@EnumAsto customize the behavior of a particular enum
To use these annotations, import the types:
import com.novus.salat.annotations._
The import statement is important! This package object import aliases each annotation to a type targeted with @getter.
If you import like this instead,
import com.novus.salat.annotations.raw.Persist
you will need to manually target to the getter like this:
@(Persist @getter) val someVal = ...
See traits and abstract superclasses with Salat
Using @Key for ad hoc key remapping is as easy as declaring it in the case class constructor:
case class Alpha(@Key("greeting") x: String)
scala> val a = Alpha(x = "Hello world")
a: com.novus.salat.test.model.Alpha = Alpha(Hello world)
scala> val dbo = grater[Alpha].asDBObject(a)
dbo: com.mongodb.casbah.Imports.DBObject = { "_typeHint" :
"com.novus.salat.test.model.Alpha" , "greeting" : "Hello world"}
scala> val a_* = grater[Alpha].asObject(dbo)
a_*: com.novus.salat.test.model.Alpha = Alpha(Hello world)
scala> a == a_*
res0: Boolean = trueSometimes you want to serialize a value inside a case class but outside its constructor. The canonical example to me is
a value you want to be able to sort on in Mongo but don't otherwise care about. @Persist to the rescue!
You can use @Persist on a val, var or lazy val.
case class Psi(x: String) {
@Persist val reversed = x.reverse
}
scala> val p = Psi(x = "persist me")
p: com.novus.salat.test.model.Psi = Psi(persist me)
scala> p.reversed
res0: String = em tsisrep
scala> val dbo = grater[Psi].asDBObject(p)
dbo: com.mongodb.casbah.Imports.DBObject = { "_typeHint" : "com.novus.salat.test.model.Psi" ,
"x" : "persist me" , "reversed" : "em tsisrep"}
scala> val p_* = grater[Psi].asObject(dbo)
p_*: com.novus.salat.test.model.Psi = Psi(persist me)But it gets better: you can also use @Persist in an immediate trait or abstract superclass. Mix and match.
If, for whatever reason, you are passing something into your case class constructor that you don't want to serialize, you need only do two things:
- annotate the parameter with
@Ignore - supply a default argument so that the object can be deserialized
case class Alpha(x: String, @Ignore y: Option[String] = None)
scala> val a = Alpha(x = "Hello world", y = Some("Goodbye value I don't care about"))
a: com.novus.salat.test.model.Alpha = Alpha(Hello world,Some(Goodbye value I don't care about))
scala> val dbo = grater[Alpha].asDBObject(a)
dbo: com.mongodb.casbah.Imports.DBObject = { "_typeHint" :
"com.novus.salat.test.model.Alpha" , "x" : "Hello world"}
scala> val a_* = grater[Alpha].asObject(dbo)
a_*: com.novus.salat.test.model.Alpha = Alpha(Hello world,Some(Goodbye value I don't care about))
scala> a == a_*
res0: Boolean = trueEnums? Our sympathies.
You have two choices for enum serialization: by id or by value. They both have their downsides. I'm assuming by this point in the game you already know what your poison is.
Salat's default enum handling is by value, set up at the context level.
But let's say that for just one enum you want to persist by value instead of id or vice versa. Very easy - just define your custom enum strategy at the enum level:
// ThugLevel will use the context default handling for enums (which is by value)
object ThugLevel extends Enumeration("Fairplay Tony", "Honour student", "Just a good boy who loves his mum", "Trouble, you") {
val One, Two, Three, Four = Value
}
// but DoneIn will be mapped by id
@EnumAs(strategy = EnumStrategy.BY_ID)
object DoneIn extends Enumeration {
val Napping, PiningForTheFjords, IsThereADoctorInTheHouse, OhDear, Definitely = Value
}
case class Hector(thug: ThugLevel.Value, doneInById: DoneIn.Value)