MongoScala3Codec
is a lightweight and efficient library that simplifies BSON serialization and deserialization for Scala case classes. Powered by Scala 3 macros, it generates BSON codecs at compile time, ensuring type safety and high performance. This library is an essential tool for seamless integration with MongoDB in Scala applications.
- Scala 3: This library is compatible only with Scala 3, leveraging its advanced macro capabilities for compile-time codec generation.
To include MongoScala3Codec in your Scala project, add the following dependency:
libraryDependencies += "io.github.mbannour" %% "mongoscala3codec" % "0.0.1-M6"
- Macro-based Codec Generation: Automatically generate BSON codecs for case classes at compile-time.
- Support for Optional Fields: Handle
Option
types with customizable behavior (encodeNone
orignoreNone
). - Nested Case Class Support: Serialize and deserialize deeply nested case class structures.
- Seamless Integration: Compatible with MongoDB Scala Driver.
Below is a complete example that demonstrates how to:
- Define your case classes.
- Generate BSON codecs using the macro-based codec generator.
- Set up a consolidated
CodecRegistry
for MongoDB. - Insert and retrieve a document from a MongoDB collection.
import org.mongodb.scala.{MongoClient, MongoCollection, MongoDatabase, *}
import io.github.mbannour.mongo.codecs.{CaseClassCodec, CodecProviderMacro}
import org.bson.codecs.configuration.{CodecProvider, CodecRegistries, CodecRegistry}
import org.bson.types.ObjectId
import org.mongodb.scala.bson.annotations.BsonProperty
import org.mongodb.scala.model.Filters
final case class EmployeeId(value: ObjectId) extends AnyVal
case class Address(street: String, city: String, zipCode: Int, employeeId: EmployeeId)
object Address {
// Define a registry for Address that includes the custom EmployeeId codec.
val registry: CodecRegistry =
CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(EmployeeId.dealerIdBsonCodec),
MongoClient.DEFAULT_CODEC_REGISTRY
)
}
case class Person(
_id: ObjectId,
@BsonProperty("n") name: String,
middleName: Option[String],
age: Int,
height: Double,
married: Boolean,
address: Option[Address],
nicknames: Seq[String]
)
object Person {
// Create a codec registry for Person that incorporates:
// - The codec provider for Address (which itself uses Address.registry)
// - The custom EmployeeId codec
// - The base MongoDB Scala Driver registry
private val personCodecRegistry: CodecRegistry =
CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(
CodecProviderMacro.createCodecProviderEncodeNone[Address](Address.registry)
),
CodecRegistries.fromCodecs(EmployeeId.dealerIdBsonCodec),
MongoClient.DEFAULT_CODEC_REGISTRY
)
}
object Main extends App {
private val personProvider: CodecProvider =
CodecProviderMacro.createCodecProviderEncodeNone[Person](personCodecRegistry)
private val combinedRegistry: CodecRegistry =
CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(personProvider),
MongoClient.DEFAULT_CODEC_REGISTRY
)
val database: MongoDatabase = MongoClient()
.getDatabase("test_db")
.withCodecRegistry(combinedRegistry)
val collection: MongoCollection[Person] = database.getCollection("people")
val person = Person(
_id = new ObjectId(),
state = Created,
name = "Alice",
middleName = None,
age = 30,
height = 5.6,
married = true,
address = None,
nicknames = Seq("Ally", "Lissie")
)
collection.insertOne(person).toFuture()
collection.find().toFuture().foreach(println)
}
This project is licensed under the MIT License. See the LICENSE file for details.
Main Developer: Mohamed Ali Bannour
Email: med.ali.bennour@gmail.com