Overview
The Scala driver allows you to use case classes to represent
documents in a collection by using the Macros helper. Simple case classes and
nested case classes are supported. Hierarchical modeling can be achieved
by using a sealed trait or class and then by having case classes implement the
parent trait.
Many simple Scala types are supported and can be marshaled into their
corresponding BsonValue type. The following list describes Scala types and their
type-safe BSON representation:
Scala Type  | BSON Type  | 
|---|---|
Case class  | Document  | 
  | Array  | 
  | Date  | 
  | Boolean  | 
  | Double  | 
  | Int32  | 
  | Int64  | 
  | String  | 
  | Binary  | 
  | Null  | 
Creating Codecs
To create a codec for your case class, use the Macros object helper
methods. You should use the
Macros.createCodecProvider() method to create a CodecProvider. A
CodecProvider passes the configured CodecRegistry to the underlying
Codec and provides access to all the configured codecs.
To create a CodecProvider, set the case class type when calling
createCodecProvider() as shown in the following code:
import org.mongodb.scala.bson.codecs.Macros case class Person(firstName: String, secondName: String) val personCodecProvider = Macros.createCodecProvider[Person]() 
The personCodecProvider can then be used when converted into a
CodecRegistry by using the CodecRegistries static helpers. The
following code creates a new codec registry, combining the new personCodecProvider
and the default codec registry:
import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders} val codecRegistry = fromRegistries( fromProviders(personCodecProvider), DEFAULT_CODEC_REGISTRY ) 
The Macros helper also has an implicit createCodecProvider() method that
takes the Class[T] and creates a CodecProvider from that. This method
is more concise especially when defining multiple providers:
import org.mongodb.scala.bson.codecs.Macros._ import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders} case class Address(firstLine: String, secondLine: String, thirdLine: String, town: String, zipCode: String) case class ClubMember(person: Person, address: Address, paid: Boolean) val codecRegistry = fromRegistries( fromProviders(classOf[ClubMember], classOf[Person], classOf[Address]), DEFAULT_CODEC_REGISTRY ) 
Sealed Classes and ADTs
Hierarchical class structures are supported through sealed traits and
classes. Each subclass is handled specifically by the generated codec,
so you only need to create a CodecProvider for the parent sealed
trait or class. Internally an extra field (_t) is stored alongside the data
so that the correct subclass can be hydrated when decoding the data.
The following code is an example of a tree-like structure containing branch and leaf
nodes:
sealed class Tree case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree case class Leaf(value: Int) extends Tree val codecRegistry = fromRegistries( fromProviders(classOf[Tree]), DEFAULT_CODEC_REGISTRY ) 
Options and None Values
By default, Option values are always stored. In driver v2.1.0, new
helpers were added so that None values would not be stored in the
database. In the following example, the driver only stores an address if
if one is present:
import org.mongodb.scala.bson.codecs.Macros case class Person(firstName: String, secondName: String, address: Option[Address]) val personCodecProvider = Macros.createCodecProviderIgnoreNone[Person]() 
Alternative Field Names
The BsonProperty annotation can be used to configure the BSON field
key to be used for a given property. The following example uses the
BsonProperty annotation to change how the firstName field is stored:
case class Person(@BsonProperty("first_name") firstName: String, secondName: String)