Skip to content

Compile-time generated BSON codecs for Scala 3 case classes, ensuring seamless and type-safe integration with MongoDB

License

Notifications You must be signed in to change notification settings

mbannour/MongoScala3Codec

Repository files navigation

MongoScala3Codec: A Macro-Based BSON Codec Generator for Scala

mongoScala3Codec version mongoScala3Codec compatibility

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.

Compatibility

  • Scala 3: This library is compatible only with Scala 3, leveraging its advanced macro capabilities for compile-time codec generation.

Installation

To include MongoScala3Codec in your Scala project, add the following dependency:

libraryDependencies += "io.github.mbannour" %% "mongoscala3codec" % "0.0.1-M6"

Features

  • 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 or ignoreNone).
  • Nested Case Class Support: Serialize and deserialize deeply nested case class structures.
  • Seamless Integration: Compatible with MongoDB Scala Driver.

Getting Started

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.

Example Code

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)

}

License

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

About

Compile-time generated BSON codecs for Scala 3 case classes, ensuring seamless and type-safe integration with MongoDB

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages