JsonPrimitive silently converts unknown Number class instances to Long
Closed this issue · 3 comments
I discovered it when debugging an issue where my preprocessor would cut off fractional parts of numbers.
I was using gson to preprocess my json to properly deal with duplicate keys and turn them into comments. In that process, the way I'm parsing numbers is by using Gson's LazilyParsedNumber
class. And I ended up just passing it into JsonPrimitive constructor. Which worked, but as I discovered, it silently turned it into a long.
What I think could make more sense is to convert it into a BigDecimal by first converting it to string (which currently doesn't appear to be supported?).
Number has Double conversion methods; I can just convert it to Double, decide if it has a fractional part, and downgrade to Long if it doesn't.
I was thinking JsonPrimitive.of(BigInteger) needed a companion JsonPrimitive.of(BigDecimal); I'll do that next.
If it doesn't have a fractional part, it may also be too big to fit in a long, in which case, might be better to use double again.
Or use BigDecimal convert to the needed type as needed later.
If it's too big to fit in a Long, then the appropriate numeric type is Double, which can handle larger whole numbers than a Long (at reduced precision). This is consistent with java allowing you to do a widening implicit cast from long to double.
I want a fairly clean conversion from "whatever's on disk" to a java datatype. And I want another parser (with the same quirks set) to be able to read what jankson writes. Other parsers will choke and die on numbers outside a 64-bit float. The Json5 spec defers to RFC7159 on this,
Since software that implements
IEEE 754-2008 binary64 (double precision) numbers [IEEE754] is
generally available and widely used, good interoperability can be
achieved by implementations that expect no more precision or range
than these provide, in the sense that implementations will
approximate JSON numbers within the expected precision. A JSON
number such as 1E400 or 3.141592653589793238462643383279 may indicate
potential interoperability problems, since it suggests that the
software that created it expects receiving software to have greater
capabilities for numeric magnitude and precision than is widely
available.
If you want larger numbers than this, in JSON, the correct pathway is to serialize them to a String, and deserialize them from a String, in which case there are JsonPrimitive methods already in place for BigInteger, and BigDecimal are planned.