GRPC clojure BigDecimal to java BigDecimal

Tags: , ,



I have a java client that is calling a Clojure service via GRPC. The problem is when we get the response back from their service it is adding letters to the end of the big decimal. When we try to convert it to a big decimal in java we get an error converting from a string to a big decimal. Any thoughts?

One other thing, our field is declared as a string in our proto, even though it is a big decimal.

FLOW info: JAVA (big decimal to string) –> GRPC –> clojure (string to big decimal then processing and then big decmial back to string) –> GRPC –> Java (string to big decimal – this is where the error is)

An example of the value we are getting back from the GRPC string that we are trying to convert to a BigDecmial in java is -840M. We could do a string replace but that seems brittle. Is there a utility to handle this?

Thanks, Brian

Answer

The problem is that the Clojure service is converting the BigDecimal value to a string using Clojure’s native print mechanism. This adds the suffix M to all BigDecimal values when using println or prn (BigInteger values get the N suffix):

(int 123)     => 123
(bigdec 123)  => 123M

The reason is that Clojure has literal forms for BigDecimal and BigInteger where you don’t need to make an explicit constructor call to use a BigDecimal in your code:

(type 12.3)   => java.lang.Double
(type 12.3M)  => java.math.BigDecimal

If you can’t change library to use another method of stringify-ing the BigDecimal value, you are safe to just strip off the last char M and then parse that BigDecimal​(String val) constructor or similar.

It might be easiest to convert to a char array, then use this constructor:

BigDecimal​(char[] in, int offset, int len)

where len is decremented by 1 to make it ignore the trailing M:

package demo;
import  java.math.BigDecimal;

public class BigDec {
  public static BigDecimal parseClojureString(String str ) {
    char[] chars = str.toCharArray();
    return new BigDecimal(chars, 0, (chars.length - 1));
  }
}

and a Clojure test:

(dotest
  (let [parsed (BigDec/parseClojureString "12.3M")]
    (spyx parsed)
    (spyx (type parsed))))

with result

parsed         => 12.3M
(type parsed)  => java.math.BigDecimal


Source: stackoverflow