diff --git a/src/number.rs b/src/number.rs index 21a76411c..ca2fd55fd 100644 --- a/src/number.rs +++ b/src/number.rs @@ -279,6 +279,24 @@ impl Number { } } + pub(crate) fn from_f32(f: f32) -> Option { + if f.is_finite() { + let n = { + #[cfg(not(feature = "arbitrary_precision"))] + { + N::Float(f as f64) + } + #[cfg(feature = "arbitrary_precision")] + { + ryu::Buffer::new().format_finite(f).to_owned() + } + }; + Some(Number { n }) + } else { + None + } + } + #[cfg(feature = "arbitrary_precision")] /// Not public API. Only tests use this. #[doc(hidden)] diff --git a/src/value/from.rs b/src/value/from.rs index c5a6a3960..462ad3f51 100644 --- a/src/value/from.rs +++ b/src/value/from.rs @@ -40,7 +40,7 @@ impl From for Value { /// let x: Value = f.into(); /// ``` fn from(f: f32) -> Self { - From::from(f as f64) + Number::from_f32(f).map_or(Value::Null, Value::Number) } } diff --git a/src/value/ser.rs b/src/value/ser.rs index a29814e92..875d22e24 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -1,6 +1,5 @@ use crate::error::{Error, ErrorCode, Result}; use crate::map::Map; -use crate::number::Number; use crate::value::{to_value, Value}; use alloc::borrow::ToOwned; use alloc::string::{String, ToString}; @@ -149,13 +148,13 @@ impl serde::Serializer for Serializer { } #[inline] - fn serialize_f32(self, value: f32) -> Result { - self.serialize_f64(value as f64) + fn serialize_f32(self, float: f32) -> Result { + Ok(Value::from(float)) } #[inline] - fn serialize_f64(self, value: f64) -> Result { - Ok(Number::from_f64(value).map_or(Value::Null, Value::Number)) + fn serialize_f64(self, float: f64) -> Result { + Ok(Value::from(float)) } #[inline] diff --git a/tests/regression/issue1004.rs b/tests/regression/issue1004.rs index d2c3e74c0..3f5bd96aa 100644 --- a/tests/regression/issue1004.rs +++ b/tests/regression/issue1004.rs @@ -5,5 +5,8 @@ fn test() { let float = 5.55f32; let value = serde_json::to_value(&float).unwrap(); let json = serde_json::to_string(&value).unwrap(); - assert_eq!(json, "5.550000190734863"); // FIXME + + // If the f32 were cast to f64 by Value before serialization, then this + // would incorrectly serialize as 5.550000190734863. + assert_eq!(json, "5.55"); }