rust-decimal icon indicating copy to clipboard operation
rust-decimal copied to clipboard

serde float_roundtrip vs rust_decimal's serde-float

Open bugproof opened this issue 2 years ago • 1 comments

How does rust-decimal deserialize and serialize f64?

https://github.com/paupino/rust-decimal/blob/master/src/serde.rs#L342-L347

It seems like it calls to_string on f64.

serde json has a feature float_roundtrip that enables perfect accuracy float parsing https://github.com/serde-rs/json/issues/536

How does it compare to what rust-decimal does?

bugproof avatar Jun 30 '22 16:06 bugproof

It's a good question. Effectively Rust Decimal has different serialization/deserialization strategies that one can adopt to match their use case. serde-float is one such strategy which causes the Rust Decimal library to use a very specific code path. Serde feature flags in Rust Decimal has become a bit complex for my liking but in general if only serde-float is enabled (i.e. no arbitrary precision):

  • Serializes using serializer.serialize_f64(self.to_f64().unwrap()) - i.e. converts directly to a float without going through a string however is limited by what can fit inside a f64.
  • Deserializes using Decimal::from_str(&value.to_string()).map_err(|_| E::invalid_value(Unexpected::Float(value), &self)) - i.e. it converts the value to a string and parses that directly into a Decimal.

In contrast, it appears that the float_roundtrip feature uses a form of lexical analysis to parse something looking like a float into a float. Not at all what rust_decimal does for float deserialization.

If you're wanting to retain precision while parsing float like fields then I'd recommend serde-arbitrary-precision to which leverages that feature flag on serde_json. This can be used in combination with serde-float so that serialization still outputs f64. Unless there is a specific use case that float_roundtrip is required?

paupino avatar Jul 18 '22 17:07 paupino