Skip to content

Instantly share code, notes, and snippets.

@sgodbillon
Last active December 17, 2015 08:59
Show Gist options
  • Save sgodbillon/5583850 to your computer and use it in GitHub Desktop.
Save sgodbillon/5583850 to your computer and use it in GitHub Desktop.
BigDecimal to BSONDouble Example with ReactiveMongo-BSON 0.9 (two versions: one is precise (the first one), the other is simpler but may lead to wrong value when the value exceeds Double.MaxValue)
import reactivemongo.bson._
// BigDecimal and BigInteger BSON Handlers – the right way :)
object BSONBigDecimalBigInteger {
implicit object BigIntHandler extends BSONDocumentReader[BigInt] with BSONDocumentWriter[BigInt] {
def write(bigInt: BigInt): BSONDocument = BSONDocument(
"signum" -> bigInt.signum,
"value" -> BSONBinary(bigInt.toByteArray, Subtype.UserDefinedSubtype))
def read(doc: BSONDocument): BigInt = BigInt(
doc.getAs[Int]("signum").get,
{
val buf = doc.getAs[BSONBinary]("value").get.value
buf.readArray(buf.readable)
})
}
implicit object BigDecimalHandler extends BSONDocumentReader[BigDecimal] with BSONDocumentWriter[BigDecimal] {
def write(bigDecimal: BigDecimal) = BSONDocument(
"scale" -> bigDecimal.scale,
"precision" -> bigDecimal.precision,
"value" -> BigInt(bigDecimal.underlying.unscaledValue()))
def read(doc: BSONDocument) = BigDecimal.apply(
doc.getAs[BigInt]("value").get,
doc.getAs[Int]("scale").get,
new java.math.MathContext(doc.getAs[Int]("precision").get))
}
// example using this
case class SomeClass(bd: BigDecimal)
implicit val someClassHandler = Macros.handler[SomeClass]
val someClassValue = SomeClass(BigDecimal(1908713, 12))
val bsonBigDecimal = BSON.writeDocument(someClassValue)
val someClassValueFromBSON = BSON.readDocument[SomeClass](bsonBigDecimal)
// prints: someClassValue == someClassValueFromBSON ? true
println(s"someClassValue == someClassValueFromBSON ? ${someClassValue equals someClassValueFromBSON}")
}
// BigDecimal to BSONDouble Example
// naive implementation, does not support values > Double.MAX_VALUE
object BigDecimalBSONNaive {
implicit object BigDecimalHandler extends BSONHandler[BSONDouble, BigDecimal] {
def read(double: BSONDouble) = BigDecimal(double.value)
def write(bd: BigDecimal) = BSONDouble(bd.toDouble)
}
case class SomeClass(bigd: BigDecimal)
// USING HAND WRITTEN HANDLER
implicit object SomeClassHandler extends BSONDocumentReader[SomeClass] with BSONDocumentWriter[SomeClass] {
def read(doc: BSONDocument) = SomeClass(doc.getAs[BigDecimal]("bigd").get)
def write(sc: SomeClass) = BSONDocument("bigd" -> sc.bigd)
}
// OR, USING MACROS
// implicit val someClassHandler = Macros.handler[SomeClass]
val sc1 = SomeClass(BigDecimal(1786381))
val bsonSc1 = BSON.write(sc1)
val sc1FromBSON = BSON.readDocument[SomeClass](bsonSc1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment