Is there any way to tell the default ruby JSON library to parse non-integer numeric values as string (or BigDecimal?) instead of floats?
ie JSON.parse('{"foo": 123.45}')['foo'].class outputs Float, which may lead to precision issues.
PD: the oj library supports loading these values as BigDecimals.
PD2: seems there isn't: https://github.com/flori/json/blob/76f41a84e2bace20c3076aba53887537e37dfdb2/lib/json/pure/parser.rb#L196
In theory JSON as a container could hold highly precise numbers, but in practice one end is generally limited to IEEE 754 double precision floating point numbers as that is what JavaScript itself is limited to. Any precision loss will already be incurred if the values are encoded in JavaScript or almost any JSON implementation.
Hence, converting to BigDecimal from the parsed Float will almost always result in no additional loss of precision:
data = JSON.parse("[1.025]")
# Float can't represent decimal values precisely, so `round` fails
data.first.round(2) # => 1.02
# Converting to big decimal improves the precision of future operations
BigDecimal.new(data.first.to_s).round(2).to_s # => "1.03"
You are much better off transporting your highly precise values as strings.
Lastly, if you really need to ruby libraries can always be monkey patched to behave how you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With