Last active
December 17, 2015 08:59
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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