You can write your own writers and readers for your models. Let’s define a model for Album, and its BSONWriter and BSONReader.
You should have noted that our reader and writer extend BSONDocumentReader[T] and BSONDocumentWriter[T]. These two traits are just a shorthand for BSONReader[B <: BSONValue, T] and BSONWriter[T, B <: BSONValue].
OK, now, what if I want to store all the tracks names of the album? Or, in other words, how can we deal with collections? First of all, you can safely infer that all sequences and sets can be serialized as BSONArrays. Using BSONArray follows the same patterns as BSONDocument.
Using BSONArray does what we want, but this code is pretty verbose. Would it not be nice to deal directly with collections?
Here again, there is a converter for Traversables of types that can be transformed into BSONValues. For example, if you have a List[Something], if there is an implicit BSONWriter of Something to some BSONValue in the scope, you can use it as is, without giving explicitly a BSONArray. The same logic applies for reading BSONArray values.
So, now we can rewrite our reader and writer for albums including tracks.
Obviously, you can combine these readers and writers to de/serialize more complex object graphs. Let’s write an Artist model, containing a list of Albums.
Here, we get an “ambiguous implicit” problem, which is normal because we have more than one Reader of BSONDocuments available in our scope (SimpleArtistReader, ArtistReader, AlbumReader, etc.). So we have to explicitly give the type of the instance we want to get from the document.