Skip to main content

rust_decimal/
serde.rs

1use crate::Decimal;
2use alloc::string::ToString;
3use core::{fmt, str::FromStr};
4use num_traits::FromPrimitive;
5use serde::{self, de::Unexpected};
6
7/// Serialize/deserialize Decimals as arbitrary precision numbers in JSON using the `arbitrary_precision` feature within `serde_json`.
8///
9/// ```
10/// # use serde::{Serialize, Deserialize};
11/// # use rust_decimal::Decimal;
12/// # use std::str::FromStr;
13///
14/// #[derive(Serialize, Deserialize)]
15/// pub struct ArbitraryExample {
16///     #[serde(with = "rust_decimal::serde::arbitrary_precision")]
17///     value: Decimal,
18/// }
19///
20/// let value = ArbitraryExample { value: Decimal::from_str("123.400").unwrap() };
21/// assert_eq!(
22///     &serde_json::to_string(&value).unwrap(),
23///     r#"{"value":123.400}"#
24/// );
25/// ```
26#[cfg(feature = "serde-with-arbitrary-precision")]
27pub mod arbitrary_precision {
28    use super::*;
29    use serde::Serialize;
30
31    pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
32    where
33        D: serde::de::Deserializer<'de>,
34    {
35        deserializer.deserialize_any(DecimalVisitor)
36    }
37
38    pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
39    where
40        S: serde::Serializer,
41    {
42        serde_json::Number::from_str(&value.to_string())
43            .map_err(serde::ser::Error::custom)?
44            .serialize(serializer)
45    }
46}
47
48/// Serialize/deserialize optional Decimals as arbitrary precision numbers in JSON using the `arbitrary_precision` feature within `serde_json`.
49///
50/// ```
51/// # use serde::{Serialize, Deserialize};
52/// # use rust_decimal::Decimal;
53/// # use std::str::FromStr;
54///
55/// #[derive(Serialize, Deserialize)]
56/// pub struct ArbitraryExample {
57///     #[serde(with = "rust_decimal::serde::arbitrary_precision_option")]
58///     value: Option<Decimal>,
59/// }
60///
61/// let value = ArbitraryExample { value: Some(Decimal::from_str("123.400").unwrap()) };
62/// assert_eq!(
63///     &serde_json::to_string(&value).unwrap(),
64///     r#"{"value":123.400}"#
65/// );
66///
67/// let value = ArbitraryExample { value: None };
68/// assert_eq!(
69///     &serde_json::to_string(&value).unwrap(),
70///     r#"{"value":null}"#
71/// );
72/// ```
73#[cfg(feature = "serde-with-arbitrary-precision")]
74pub mod arbitrary_precision_option {
75    use super::*;
76    use serde::Serialize;
77
78    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
79    where
80        D: serde::de::Deserializer<'de>,
81    {
82        deserializer.deserialize_option(OptionDecimalVisitor)
83    }
84
85    pub fn serialize<S>(value: &Option<Decimal>, serializer: S) -> Result<S::Ok, S::Error>
86    where
87        S: serde::Serializer,
88    {
89        match *value {
90            Some(ref decimal) => serde_json::Number::from_str(&decimal.to_string())
91                .map_err(serde::ser::Error::custom)?
92                .serialize(serializer),
93            None => serializer.serialize_none(),
94        }
95    }
96}
97
98/// Serialize/deserialize Decimals as floats.
99///
100/// ```
101/// # use serde::{Serialize, Deserialize};
102/// # use rust_decimal::Decimal;
103/// # use std::str::FromStr;
104///
105/// #[derive(Serialize, Deserialize)]
106/// pub struct FloatExample {
107///     #[serde(with = "rust_decimal::serde::float")]
108///     value: Decimal,
109/// }
110///
111/// let value = FloatExample { value: Decimal::from_str("123.400").unwrap() };
112/// assert_eq!(
113///     &serde_json::to_string(&value).unwrap(),
114///     r#"{"value":123.4}"#
115/// );
116/// ```
117#[cfg(feature = "serde-with-float")]
118pub mod float {
119    use super::*;
120    use serde::Serialize;
121
122    pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
123    where
124        D: serde::de::Deserializer<'de>,
125    {
126        deserializer.deserialize_any(DecimalVisitor)
127    }
128
129    pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
130    where
131        S: serde::Serializer,
132    {
133        use num_traits::ToPrimitive;
134        value.to_f64().unwrap().serialize(serializer)
135    }
136}
137
138/// Serialize/deserialize optional Decimals as floats.
139///
140/// ```
141/// # use serde::{Serialize, Deserialize};
142/// # use rust_decimal::Decimal;
143/// # use std::str::FromStr;
144///
145/// #[derive(Serialize, Deserialize)]
146/// pub struct FloatExample {
147///     #[serde(with = "rust_decimal::serde::float_option")]
148///     value: Option<Decimal>,
149/// }
150///
151/// let value = FloatExample { value: Some(Decimal::from_str("123.400").unwrap()) };
152/// assert_eq!(
153///     &serde_json::to_string(&value).unwrap(),
154///     r#"{"value":123.4}"#
155/// );
156///
157/// let value = FloatExample { value: None };
158/// assert_eq!(
159///     &serde_json::to_string(&value).unwrap(),
160///     r#"{"value":null}"#
161/// );
162/// ```
163#[cfg(feature = "serde-with-float")]
164pub mod float_option {
165    use super::*;
166    use serde::Serialize;
167
168    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
169    where
170        D: serde::de::Deserializer<'de>,
171    {
172        deserializer.deserialize_option(OptionDecimalVisitor)
173    }
174
175    pub fn serialize<S>(value: &Option<Decimal>, serializer: S) -> Result<S::Ok, S::Error>
176    where
177        S: serde::Serializer,
178    {
179        match *value {
180            Some(ref decimal) => {
181                use num_traits::ToPrimitive;
182                decimal.to_f64().unwrap().serialize(serializer)
183            }
184            None => serializer.serialize_none(),
185        }
186    }
187}
188
189/// Serialize/deserialize Decimals as strings. This is particularly useful when using binary encoding formats.
190///
191/// ```
192/// # use serde::{Serialize, Deserialize};
193/// # use rust_decimal::Decimal;
194/// # use std::str::FromStr;
195///
196/// #[derive(Serialize, Deserialize)]
197/// pub struct StringExample {
198///     #[serde(with = "rust_decimal::serde::str")]
199///     value: Decimal,
200/// }
201///
202/// let value = StringExample { value: Decimal::from_str("123.400").unwrap() };
203/// assert_eq!(
204///     &serde_json::to_string(&value).unwrap(),
205///     r#"{"value":"123.400"}"#
206/// );
207///
208/// ```
209#[cfg(feature = "serde-with-str")]
210pub mod str {
211    use super::*;
212
213    pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
214    where
215        D: serde::de::Deserializer<'de>,
216    {
217        deserializer.deserialize_str(DecimalVisitor)
218    }
219
220    pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
221    where
222        S: serde::Serializer,
223    {
224        let value = crate::str::to_str_internal(value, true, None);
225        serializer.serialize_str(value.0.as_ref())
226    }
227}
228
229/// Serialize/deserialize optional Decimals as strings. This is particularly useful when using binary encoding formats.
230///
231/// ```
232/// # use serde::{Serialize, Deserialize};
233/// # use rust_decimal::Decimal;
234/// # use std::str::FromStr;
235///
236/// #[derive(Serialize, Deserialize)]
237/// pub struct StringExample {
238///     #[serde(with = "rust_decimal::serde::str_option")]
239///     value: Option<Decimal>,
240/// }
241///
242/// let value = StringExample { value: Some(Decimal::from_str("123.400").unwrap()) };
243/// assert_eq!(
244///     &serde_json::to_string(&value).unwrap(),
245///     r#"{"value":"123.400"}"#
246/// );
247///
248/// let value = StringExample { value: None };
249/// assert_eq!(
250///     &serde_json::to_string(&value).unwrap(),
251///     r#"{"value":null}"#
252/// );
253/// ```
254#[cfg(feature = "serde-with-str")]
255pub mod str_option {
256    use super::*;
257
258    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
259    where
260        D: serde::de::Deserializer<'de>,
261    {
262        deserializer.deserialize_option(OptionDecimalStrVisitor)
263    }
264
265    pub fn serialize<S>(value: &Option<Decimal>, serializer: S) -> Result<S::Ok, S::Error>
266    where
267        S: serde::Serializer,
268    {
269        match *value {
270            Some(ref decimal) => {
271                let decimal = crate::str::to_str_internal(decimal, true, None);
272                serializer.serialize_some::<str>(decimal.0.as_ref())
273            }
274            None => serializer.serialize_none(),
275        }
276    }
277}
278
279#[cfg(not(feature = "serde-str"))]
280impl<'de> serde::Deserialize<'de> for Decimal {
281    fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
282    where
283        D: serde::de::Deserializer<'de>,
284    {
285        deserializer.deserialize_any(DecimalVisitor)
286    }
287}
288
289#[cfg(all(feature = "serde-str", not(feature = "serde-float")))]
290impl<'de> serde::Deserialize<'de> for Decimal {
291    fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
292    where
293        D: serde::de::Deserializer<'de>,
294    {
295        deserializer.deserialize_str(DecimalVisitor)
296    }
297}
298
299#[cfg(all(feature = "serde-str", feature = "serde-float"))]
300impl<'de> serde::Deserialize<'de> for Decimal {
301    fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
302    where
303        D: serde::de::Deserializer<'de>,
304    {
305        deserializer.deserialize_f64(DecimalVisitor)
306    }
307}
308
309// It's a shame this needs to be redefined for this feature and not able to be referenced directly
310#[cfg(feature = "serde-with-arbitrary-precision")]
311const DECIMAL_KEY_TOKEN: &str = "$serde_json::private::Number";
312
313struct DecimalVisitor;
314
315impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
316    type Value = Decimal;
317
318    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
319        write!(formatter, "a Decimal type representing a fixed-point number")
320    }
321
322    fn visit_i64<E>(self, value: i64) -> Result<Decimal, E>
323    where
324        E: serde::de::Error,
325    {
326        match Decimal::from_i64(value) {
327            Some(s) => Ok(s),
328            None => Err(E::invalid_value(Unexpected::Signed(value), &self)),
329        }
330    }
331
332    fn visit_u64<E>(self, value: u64) -> Result<Decimal, E>
333    where
334        E: serde::de::Error,
335    {
336        match Decimal::from_u64(value) {
337            Some(s) => Ok(s),
338            None => Err(E::invalid_value(Unexpected::Unsigned(value), &self)),
339        }
340    }
341
342    #[cfg(not(feature = "serde-with-arbitrary-precision"))]
343    fn visit_f64<E>(self, value: f64) -> Result<Decimal, E>
344    where
345        E: serde::de::Error,
346    {
347        Decimal::from_str(&value.to_string()).map_err(|_| E::invalid_value(Unexpected::Float(value), &self))
348    }
349
350    #[cfg(feature = "serde-with-arbitrary-precision")]
351    fn visit_f64<E>(self, value: f64) -> Result<Decimal, E>
352    where
353        E: serde::de::Error,
354    {
355        let mut buf = zmij::Buffer::new();
356        let formatted = buf.format_finite(value);
357        Decimal::from_str(formatted)
358            .or_else(|_| Decimal::from_scientific(formatted))
359            .map_err(|_| E::invalid_value(Unexpected::Float(value), &self))
360    }
361
362    fn visit_str<E>(self, value: &str) -> Result<Decimal, E>
363    where
364        E: serde::de::Error,
365    {
366        Decimal::from_str(value)
367            .or_else(|_| Decimal::from_scientific(value))
368            .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
369    }
370
371    #[cfg(feature = "serde-with-arbitrary-precision")]
372    fn visit_map<A>(self, map: A) -> Result<Decimal, A::Error>
373    where
374        A: serde::de::MapAccess<'de>,
375    {
376        let mut map = map;
377        let value = map.next_key::<DecimalKey>()?;
378        if value.is_none() {
379            return Err(serde::de::Error::invalid_type(Unexpected::Map, &self));
380        }
381        let v: DecimalFromString = map.next_value()?;
382        Ok(v.value)
383    }
384}
385
386#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))]
387struct OptionDecimalVisitor;
388
389#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))]
390impl<'de> serde::de::Visitor<'de> for OptionDecimalVisitor {
391    type Value = Option<Decimal>;
392
393    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
394        formatter.write_str("a Decimal type representing a fixed-point number")
395    }
396
397    fn visit_none<E>(self) -> Result<Option<Decimal>, E>
398    where
399        E: serde::de::Error,
400    {
401        Ok(None)
402    }
403
404    #[cfg(all(feature = "serde-str", feature = "serde-float"))]
405    fn visit_some<D>(self, d: D) -> Result<Option<Decimal>, D::Error>
406    where
407        D: serde::de::Deserializer<'de>,
408    {
409        // We've got multiple types that we may see so we need to use any
410        d.deserialize_any(DecimalVisitor).map(Some)
411    }
412
413    #[cfg(not(all(feature = "serde-str", feature = "serde-float")))]
414    fn visit_some<D>(self, d: D) -> Result<Option<Decimal>, D::Error>
415    where
416        D: serde::de::Deserializer<'de>,
417    {
418        <Decimal as serde::Deserialize>::deserialize(d).map(Some)
419    }
420}
421
422#[cfg(feature = "serde-with-str")]
423struct OptionDecimalStrVisitor;
424
425#[cfg(feature = "serde-with-str")]
426impl<'de> serde::de::Visitor<'de> for OptionDecimalStrVisitor {
427    type Value = Option<Decimal>;
428
429    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
430        formatter.write_str("a Decimal type representing a fixed-point number")
431    }
432
433    fn visit_none<E>(self) -> Result<Option<Decimal>, E>
434    where
435        E: serde::de::Error,
436    {
437        Ok(None)
438    }
439
440    fn visit_some<D>(self, d: D) -> Result<Option<Decimal>, D::Error>
441    where
442        D: serde::de::Deserializer<'de>,
443    {
444        d.deserialize_str(Self)
445    }
446
447    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
448    where
449        E: serde::de::Error,
450    {
451        match v.is_empty() {
452            true => Ok(None),
453            false => {
454                let d = Decimal::from_str(v)
455                    .or_else(|_| Decimal::from_scientific(v))
456                    .map_err(serde::de::Error::custom)?;
457                Ok(Some(d))
458            }
459        }
460    }
461}
462
463#[cfg(feature = "serde-with-arbitrary-precision")]
464struct DecimalKey;
465
466#[cfg(feature = "serde-with-arbitrary-precision")]
467impl<'de> serde::de::Deserialize<'de> for DecimalKey {
468    fn deserialize<D>(deserializer: D) -> Result<DecimalKey, D::Error>
469    where
470        D: serde::de::Deserializer<'de>,
471    {
472        struct FieldVisitor;
473
474        impl<'de> serde::de::Visitor<'de> for FieldVisitor {
475            type Value = ();
476
477            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
478                formatter.write_str("a valid decimal field")
479            }
480
481            fn visit_str<E>(self, s: &str) -> Result<(), E>
482            where
483                E: serde::de::Error,
484            {
485                if s == DECIMAL_KEY_TOKEN {
486                    Ok(())
487                } else {
488                    Err(serde::de::Error::custom("expected field with custom name"))
489                }
490            }
491        }
492
493        deserializer.deserialize_identifier(FieldVisitor)?;
494        Ok(DecimalKey)
495    }
496}
497
498#[cfg(feature = "serde-with-arbitrary-precision")]
499pub struct DecimalFromString {
500    pub value: Decimal,
501}
502
503#[cfg(feature = "serde-with-arbitrary-precision")]
504impl<'de> serde::de::Deserialize<'de> for DecimalFromString {
505    fn deserialize<D>(deserializer: D) -> Result<DecimalFromString, D::Error>
506    where
507        D: serde::de::Deserializer<'de>,
508    {
509        struct Visitor;
510
511        impl<'de> serde::de::Visitor<'de> for Visitor {
512            type Value = DecimalFromString;
513
514            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
515                formatter.write_str("string containing a decimal")
516            }
517
518            fn visit_str<E>(self, value: &str) -> Result<DecimalFromString, E>
519            where
520                E: serde::de::Error,
521            {
522                let d = Decimal::from_str(value)
523                    .or_else(|_| Decimal::from_scientific(value))
524                    .map_err(serde::de::Error::custom)?;
525                Ok(DecimalFromString { value: d })
526            }
527        }
528
529        deserializer.deserialize_str(Visitor)
530    }
531}
532
533#[cfg(not(feature = "serde-float"))]
534impl serde::Serialize for Decimal {
535    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
536    where
537        S: serde::Serializer,
538    {
539        let value = crate::str::to_str_internal(self, true, None);
540        serializer.serialize_str(value.0.as_ref())
541    }
542}
543
544#[cfg(all(feature = "serde-float", not(feature = "serde-arbitrary-precision")))]
545impl serde::Serialize for Decimal {
546    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
547    where
548        S: serde::Serializer,
549    {
550        use num_traits::ToPrimitive;
551        serializer.serialize_f64(self.to_f64().unwrap())
552    }
553}
554
555#[cfg(all(feature = "serde-float", feature = "serde-arbitrary-precision"))]
556impl serde::Serialize for Decimal {
557    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
558    where
559        S: serde::Serializer,
560    {
561        serde_json::Number::from_str(&self.to_string())
562            .map_err(serde::ser::Error::custom)?
563            .serialize(serializer)
564    }
565}
566
567#[cfg(test)]
568mod test {
569    use super::*;
570    use serde::{Deserialize, Serialize};
571
572    #[derive(Serialize, Deserialize, Debug)]
573    struct Record {
574        amount: Decimal,
575    }
576
577    #[test]
578    #[cfg(not(feature = "serde-str"))]
579    fn deserialize_valid_decimal() {
580        let data = [
581            ("{\"amount\":\"1.234\"}", "1.234"),
582            ("{\"amount\":1234}", "1234"),
583            ("{\"amount\":1234.56}", "1234.56"),
584            ("{\"amount\":\"1.23456e3\"}", "1234.56"),
585        ];
586        for &(serialized, value) in data.iter() {
587            let result = serde_json::from_str(serialized);
588            assert!(
589                result.is_ok(),
590                "expected successful deserialization for {}. Error: {:?}",
591                serialized,
592                result.err().unwrap()
593            );
594            let record: Record = result.unwrap();
595            assert_eq!(
596                value,
597                record.amount.to_string(),
598                "expected: {}, actual: {}",
599                value,
600                record.amount
601            );
602        }
603    }
604
605    #[test]
606    #[cfg(feature = "serde-arbitrary-precision")]
607    fn deserialize_basic_decimal() {
608        let d: Decimal = serde_json::from_str("1.1234127836128763").unwrap();
609        // Typically, this would not work without this feature enabled due to rounding
610        assert_eq!(d.to_string(), "1.1234127836128763");
611    }
612
613    #[test]
614    #[cfg(feature = "serde-arbitrary-precision")]
615    fn deserialize_f64_scientific_notation_from_value() {
616        // When serde_json's arbitrary_precision is enabled, small floats that roundtrip
617        // through f64 are deserialized via visit_f64. zmij/ryu formats them in scientific
618        // notation (e.g. "5.06e-6") which Decimal::from_str doesn't support.
619        // This test ensures visit_f64 falls back to from_scientific.
620        let json: serde_json::Value = serde_json::from_str(r#"{"amount": 5.06e-6}"#).unwrap();
621        let record: Record = serde_json::from_value(json).unwrap();
622        assert_eq!(record.amount.to_string(), "0.00000506");
623    }
624
625    #[test]
626    #[should_panic]
627    fn deserialize_invalid_decimal() {
628        let serialized = "{\"amount\":\"foo\"}";
629        let _: Record = serde_json::from_str(serialized).unwrap();
630    }
631
632    #[test]
633    #[cfg(not(feature = "serde-float"))]
634    fn serialize_decimal() {
635        let record = Record {
636            amount: Decimal::new(1234, 3),
637        };
638        let serialized = serde_json::to_string(&record).unwrap();
639        assert_eq!("{\"amount\":\"1.234\"}", serialized);
640    }
641
642    #[test]
643    #[cfg(not(feature = "serde-float"))]
644    fn serialize_negative_zero() {
645        let record = Record { amount: -Decimal::ZERO };
646        let serialized = serde_json::to_string(&record).unwrap();
647        assert_eq!("{\"amount\":\"-0\"}", serialized);
648    }
649
650    #[test]
651    #[cfg(feature = "serde-float")]
652    fn serialize_decimal() {
653        let record = Record {
654            amount: Decimal::new(1234, 3),
655        };
656        let serialized = serde_json::to_string(&record).unwrap();
657        assert_eq!("{\"amount\":1.234}", serialized);
658    }
659
660    #[test]
661    #[cfg(all(feature = "serde-float", feature = "serde-arbitrary-precision"))]
662    fn serialize_decimal_roundtrip() {
663        let record = Record {
664            // 4.81 is intentionally chosen as it is unrepresentable as a floating point number, meaning this test
665            // would fail if the `serde-arbitrary-precision` was not activated.
666            amount: Decimal::new(481, 2),
667        };
668        let serialized = serde_json::to_string(&record).unwrap();
669        assert_eq!("{\"amount\":4.81}", serialized);
670        let deserialized: Record = serde_json::from_str(&serialized).unwrap();
671        assert_eq!(record.amount, deserialized.amount);
672    }
673
674    #[test]
675    #[cfg(all(feature = "serde-float", feature = "serde-arbitrary-precision"))]
676    fn serialize_whole_number_decimal() {
677        let data = [
678            ("0", "0"),
679            ("1.0", "1.0"),
680            ("0.00", "0.00"),
681            ("1.234", "1.234"),
682            ("3.14159", "3.14159"),
683            ("-3.14159", "-3.14159"),
684            ("1234567890123.4567890", "1234567890123.4567890"),
685            ("-1234567890123.4567890", "-1234567890123.4567890"),
686        ];
687
688        for &(value, expected) in data.iter() {
689            let record = Record {
690                amount: Decimal::from_str(value).unwrap(),
691            };
692
693            let serialized = serde_json::to_string(&record).unwrap();
694            let value: serde_json::Value = serde_json::from_str(&serialized).unwrap();
695            let deserialized: Record = serde_json::from_value(value).unwrap();
696
697            assert_eq!(expected, deserialized.amount.to_string());
698        }
699    }
700
701    #[test]
702    #[cfg(all(feature = "serde-str", not(feature = "serde-float")))]
703    fn serialize_decimal_roundtrip() {
704        let record = Record {
705            amount: Decimal::new(481, 2),
706        };
707        let serialized = serde_json::to_string(&record).unwrap();
708        assert_eq!("{\"amount\":\"4.81\"}", serialized);
709        let deserialized: Record = serde_json::from_str(&serialized).unwrap();
710        assert_eq!(record.amount, deserialized.amount);
711    }
712
713    #[test]
714    #[cfg(all(feature = "serde-str", not(feature = "serde-float")))]
715    fn bincode_serialization_not_float() {
716        use bincode::{deserialize, serialize};
717
718        let data = [
719            "0",
720            "0.00",
721            "3.14159",
722            "-3.14159",
723            "1234567890123.4567890",
724            "-1234567890123.4567890",
725            "5233.9008808150288439427720175",
726            "-5233.9008808150288439427720175",
727        ];
728        for &raw in data.iter() {
729            let value = Decimal::from_str(raw).unwrap();
730            let encoded = serialize(&value).unwrap();
731            let decoded: Decimal = deserialize(&encoded[..]).unwrap();
732            assert_eq!(value, decoded);
733            assert_eq!(8usize + raw.len(), encoded.len());
734        }
735    }
736
737    #[test]
738    #[cfg(all(feature = "serde-str", feature = "serde-float"))]
739    fn bincode_serialization_serde_float() {
740        use bincode::{deserialize, serialize};
741
742        let data = [
743            ("0", "0"),
744            ("0.00", "0.00"),
745            ("3.14159", "3.14159"),
746            ("-3.14159", "-3.14159"),
747            ("1234567890123.4567890", "1234567890123.4568"),
748            ("-1234567890123.4567890", "-1234567890123.4568"),
749        ];
750        for &(value, expected) in data.iter() {
751            let value = Decimal::from_str(value).unwrap();
752            let expected = Decimal::from_str(expected).unwrap();
753            let encoded = serialize(&value).unwrap();
754            let decoded: Decimal = deserialize(&encoded[..]).unwrap();
755            assert_eq!(expected, decoded);
756            assert_eq!(8usize, encoded.len());
757        }
758    }
759
760    #[test]
761    #[cfg(all(feature = "serde-str", not(feature = "serde-float")))]
762    fn bincode_nested_serialization() {
763        // Issue #361
764        #[derive(Deserialize, Serialize, Debug)]
765        pub struct Foo {
766            value: Decimal,
767        }
768
769        let s = Foo {
770            value: Decimal::new(-1, 3).round_dp(0),
771        };
772        let ser = bincode::serialize(&s).unwrap();
773        let des: Foo = bincode::deserialize(&ser).unwrap();
774        assert_eq!(des.value, s.value);
775    }
776
777    #[test]
778    #[cfg(feature = "serde-with-arbitrary-precision")]
779    fn with_arbitrary_precision() {
780        #[derive(Serialize, Deserialize)]
781        pub struct ArbitraryExample {
782            #[serde(with = "crate::serde::arbitrary_precision")]
783            value: Decimal,
784        }
785
786        let value = ArbitraryExample {
787            value: Decimal::from_str("123.400").unwrap(),
788        };
789        assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.400}"#);
790    }
791
792    #[test]
793    #[cfg(feature = "serde-with-arbitrary-precision")]
794    fn with_arbitrary_precision_from_string() {
795        #[derive(Serialize, Deserialize)]
796        pub struct ArbitraryExample {
797            #[serde(with = "crate::serde::arbitrary_precision")]
798            value: Decimal,
799        }
800
801        let value: ArbitraryExample = serde_json::from_str(r#"{"value":"1.1234127836128763"}"#).unwrap();
802        assert_eq!(value.value.to_string(), "1.1234127836128763");
803    }
804
805    #[test]
806    #[cfg(feature = "serde-with-float")]
807    fn with_float() {
808        #[derive(Serialize, Deserialize)]
809        pub struct FloatExample {
810            #[serde(with = "crate::serde::float")]
811            value: Decimal,
812        }
813
814        let value = FloatExample {
815            value: Decimal::from_str("123.400").unwrap(),
816        };
817        assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.4}"#);
818    }
819
820    #[test]
821    #[cfg(feature = "serde-with-str")]
822    fn with_str() {
823        #[derive(Serialize, Deserialize)]
824        pub struct StringExample {
825            #[serde(with = "crate::serde::str")]
826            value: Decimal,
827        }
828
829        let value = StringExample {
830            value: Decimal::from_str("123.400").unwrap(),
831        };
832        assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":"123.400"}"#);
833    }
834
835    #[test]
836    #[cfg(feature = "serde-with-str")]
837    fn with_str_bincode() {
838        use bincode::{deserialize, serialize};
839
840        #[derive(Serialize, Deserialize)]
841        struct BincodeExample {
842            #[serde(with = "crate::serde::str")]
843            value: Decimal,
844        }
845
846        let data = [
847            ("0", "0"),
848            ("0.00", "0.00"),
849            ("1.234", "1.234"),
850            ("3.14159", "3.14159"),
851            ("-3.14159", "-3.14159"),
852            ("1234567890123.4567890", "1234567890123.4567890"),
853            ("-1234567890123.4567890", "-1234567890123.4567890"),
854        ];
855        for &(value, expected) in data.iter() {
856            let value = Decimal::from_str(value).unwrap();
857            let expected = Decimal::from_str(expected).unwrap();
858            let input = BincodeExample { value };
859
860            let encoded = serialize(&input).unwrap();
861            let decoded: BincodeExample = deserialize(&encoded[..]).unwrap();
862            assert_eq!(expected, decoded.value);
863        }
864    }
865
866    #[test]
867    #[cfg(feature = "serde-with-str")]
868    fn with_str_bincode_optional() {
869        use bincode::{deserialize, serialize};
870
871        #[derive(Serialize, Deserialize)]
872        struct BincodeExample {
873            #[serde(with = "crate::serde::str_option")]
874            value: Option<Decimal>,
875        }
876
877        // Some(value)
878        let value = Some(Decimal::new(1234, 3));
879        let input = BincodeExample { value };
880        let encoded = serialize(&input).unwrap();
881        let decoded: BincodeExample = deserialize(&encoded[..]).unwrap();
882        assert_eq!(value, decoded.value, "Some(value)");
883
884        // None
885        let input = BincodeExample { value: None };
886        let encoded = serialize(&input).unwrap();
887        let decoded: BincodeExample = deserialize(&encoded[..]).unwrap();
888        assert_eq!(None, decoded.value, "None");
889    }
890
891    #[test]
892    #[cfg(feature = "serde-with-str")]
893    fn with_str_optional() {
894        #[derive(Serialize, Deserialize)]
895        pub struct StringExample {
896            #[serde(with = "crate::serde::str_option")]
897            value: Option<Decimal>,
898        }
899
900        let original = StringExample {
901            value: Some(Decimal::from_str("123.400").unwrap()),
902        };
903        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":"123.400"}"#);
904        let deserialized: StringExample = serde_json::from_str(r#"{"value":"123.400"}"#).unwrap();
905        assert_eq!(deserialized.value, original.value);
906        assert!(deserialized.value.is_some());
907        assert_eq!(deserialized.value.unwrap().unpack(), original.value.unwrap().unpack());
908
909        // Null tests
910        let original = StringExample { value: None };
911        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":null}"#);
912        let deserialized: StringExample = serde_json::from_str(r#"{"value":null}"#).unwrap();
913        assert_eq!(deserialized.value, original.value);
914        assert!(deserialized.value.is_none());
915
916        // Empty string deserialization tests
917        let original = StringExample { value: None };
918        let deserialized: StringExample = serde_json::from_str(r#"{"value":""}"#).unwrap();
919        assert_eq!(deserialized.value, original.value);
920        assert!(deserialized.value.is_none());
921    }
922
923    #[test]
924    #[cfg(feature = "serde-with-float")]
925    fn with_float_optional() {
926        #[derive(Serialize, Deserialize)]
927        pub struct StringExample {
928            #[serde(with = "crate::serde::float_option")]
929            value: Option<Decimal>,
930        }
931
932        let original = StringExample {
933            value: Some(Decimal::from_str("123.400").unwrap()),
934        };
935        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":123.4}"#);
936        let deserialized: StringExample = serde_json::from_str(r#"{"value":123.4}"#).unwrap();
937        assert_eq!(deserialized.value, original.value);
938        assert!(deserialized.value.is_some()); // Scale is different!
939
940        // Null tests
941        let original = StringExample { value: None };
942        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":null}"#);
943        let deserialized: StringExample = serde_json::from_str(r#"{"value":null}"#).unwrap();
944        assert_eq!(deserialized.value, original.value);
945        assert!(deserialized.value.is_none());
946    }
947
948    #[test]
949    #[cfg(feature = "serde-with-arbitrary-precision")]
950    fn with_arbitrary_precision_optional() {
951        #[derive(Serialize, Deserialize)]
952        pub struct StringExample {
953            #[serde(with = "crate::serde::arbitrary_precision_option")]
954            value: Option<Decimal>,
955        }
956
957        let original = StringExample {
958            value: Some(Decimal::from_str("123.400").unwrap()),
959        };
960        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":123.400}"#);
961        let deserialized: StringExample = serde_json::from_str(r#"{"value":123.400}"#).unwrap();
962        assert_eq!(deserialized.value, original.value);
963        assert!(deserialized.value.is_some());
964        assert_eq!(deserialized.value.unwrap().unpack(), original.value.unwrap().unpack());
965
966        // Null tests
967        let original = StringExample { value: None };
968        assert_eq!(&serde_json::to_string(&original).unwrap(), r#"{"value":null}"#);
969        let deserialized: StringExample = serde_json::from_str(r#"{"value":null}"#).unwrap();
970        assert_eq!(deserialized.value, original.value);
971        assert!(deserialized.value.is_none());
972    }
973}