Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid scientific notation in circe JSON serialization

Let's say I have the next case class:

case class Person(id: String, money: BigDecimal)

object Person {
  implicit val encoder: Encoder[Person] = Encoder.forProduct2("ID", "Money")(u =>
    (u.id, u.money))

I want to serialize instances of the Person class to JSON, so when I evaluate the asJson from circe, I get the result in scientific notation:

{
    "ID" : "123",
    "VALOR_SAP" : 2.7E+7
}

Why do this happens? I think the reason is because the default to string of BigDecimal automatically format to scientific notation.

What could I do to avoid this? May be creating another type which extends from BigDecimal and overriding the toString?

like image 938
Iván Portilla Avatar asked Oct 19 '25 01:10

Iván Portilla


1 Answers

I assume that you use scala.math.BigDecimal, for java.math.BigDecimal code is similar. The way to change how objects are serialized is to provide corresponding implicit Encoder object. Unfortunately both Json and JsonNumber hierachies are sealed, so there is no very clean solution but you still can use JsonNumber.fromDecimalStringUnsafe that implements toString to just return any string you passed in. So you can do something like this:

case class Person(id: String, money: BigDecimal)

object Person {
  implicit final val bigDecimalAsPlainStringEncoder: Encoder[BigDecimal] = new Encoder[BigDecimal] {
    final def apply(value: BigDecimal): Json = Json.fromJsonNumber(JsonNumber.fromDecimalStringUnsafe(value.bigDecimal.toPlainString))
  }

  implicit val encoder: Encoder[Person] = Encoder.forProduct2("ID", "Money")(u => (u.id, u.money))

}
like image 142
SergGr Avatar answered Oct 21 '25 14:10

SergGr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!