From 3feff56791b635abbfc9f5e097195a9130d72577 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Gupta Date: Wed, 12 Jun 2024 17:50:12 +0530 Subject: [PATCH] update the codec for big decimal (#663) (#687) * update the codec for big decimal (#663) refer the codec defintion in zio-bson repo : zio/zio-bson/src/main/scala/zio/bson/BsonCodec.scala#L80 * add test case for BigDecimal's codec (#663) --- .../zio/schema/codec/BsonSchemaCodec.scala | 2 +- .../schema/codec/BsonSchemaCodecSpec.scala | 21 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala b/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala index 2531f4f97..bf3298813 100644 --- a/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala +++ b/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala @@ -412,7 +412,7 @@ object BsonSchemaCodec { case StandardType.BinaryType => BsonCodec.byteIterable[Chunk].asInstanceOf[BsonCodec[A]] case StandardType.CharType => BsonCodec.char.asInstanceOf[BsonCodec[A]] case StandardType.BigIntegerType => BsonCodec.bigInteger.asInstanceOf[BsonCodec[A]] - case StandardType.BigDecimalType => BsonCodec.bigDecimal.asInstanceOf[BsonCodec[A]] + case StandardType.BigDecimalType => BsonCodec.javaBigDecimal.asInstanceOf[BsonCodec[A]] case StandardType.UUIDType => BsonCodec.uuid.asInstanceOf[BsonCodec[A]] case StandardType.DayOfWeekType => BsonCodec.dayOfWeek.asInstanceOf[BsonCodec[A]] // BsonCodec[java.time.DayOfWeek] diff --git a/zio-schema-bson/src/test/scala/zio/schema/codec/BsonSchemaCodecSpec.scala b/zio-schema-bson/src/test/scala/zio/schema/codec/BsonSchemaCodecSpec.scala index 0ee22827b..941dc1450 100644 --- a/zio-schema-bson/src/test/scala/zio/schema/codec/BsonSchemaCodecSpec.scala +++ b/zio-schema-bson/src/test/scala/zio/schema/codec/BsonSchemaCodecSpec.scala @@ -2,12 +2,12 @@ package zio.schema.codec import scala.reflect.{ ClassTag, classTag } -import org.bson._ import org.bson.codecs.configuration.CodecRegistry import org.bson.codecs.{ Codec => BCodec, DecoderContext, EncoderContext } import org.bson.conversions.Bson import org.bson.io.BasicOutputBuffer -import org.bson.types.ObjectId +import org.bson.types.{ Decimal128, ObjectId } +import org.bson.{ BsonDecimal128, _ } import zio.bson.BsonBuilder._ import zio.bson._ @@ -24,6 +24,13 @@ object BsonSchemaCodecSpec extends ZIOSpecDefault { implicit lazy val codec: BsonCodec[SimpleClass] = BsonSchemaCodec.bsonCodec(schema) } + case class BigDecimalClass(value: BigDecimal) + + object BigDecimalClass { + implicit val schema: Schema[BigDecimalClass] = DeriveSchema.gen + implicit lazy val codec: BsonCodec[BigDecimalClass] = BsonSchemaCodec.bsonCodec(schema) + } + sealed trait Tree object Tree { @@ -79,6 +86,10 @@ object BsonSchemaCodecSpec extends ZIOSpecDefault { } yield Customer(id, name, age, friends) } + // Custom generator for BigDecimal values with rounding to ensure exact representation as Decimal128 + def genRoundedBigDecimal(scale: Int): Gen[Any, BigDecimal] = + Gen.double.map(d => BigDecimal(d).setScale(scale, BigDecimal.RoundingMode.HALF_UP)) + def spec: Spec[TestEnvironment with Scope, Any] = suite("BsonSchemaCodecSpec")( suite("round trip")( roundTripTest("SimpleClass")( @@ -107,6 +118,12 @@ object BsonSchemaCodecSpec extends ZIOSpecDefault { Customer.example.invitedFriends.map(_.value.toBsonValue): _* ) ) + ), + roundTripTest("BigDecimalClass")( + // 14 decimal places in the assert value below + genRoundedBigDecimal(14).map(BigDecimalClass(_)), + BigDecimalClass(BigDecimal("279.00000000000000")), + doc("value" -> new BsonDecimal128(Decimal128.parse("279.00000000000000"))) ) ), suite("configuration")(