Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusion how serde decimal support works #696

Closed
pronebird opened this issue Jan 1, 2025 · 1 comment
Closed

Confusion how serde decimal support works #696

pronebird opened this issue Jan 1, 2025 · 1 comment
Labels

Comments

@pronebird
Copy link

pronebird commented Jan 1, 2025

Hi,

Today I wrote a struct with one field using #[serde(with = "rust_decimal::serde::str")] and the other not:

#[serde(Serialize, Deserialize)]
struct S {
  #[serde(with = "rust_decimal::serde::str")]
  pub field_a: Decimal,
  pub field_b: Decimal
}

Which surprise compiled. That begs the question what is going on with field a and b.

So I traced the execution and found that the field A is serialized with rust_decimal::serde::str::serialize:

pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    let value = crate::str::to_str_internal(value, true, None);
    serializer.serialize_str(value.0.as_ref())
}

The field B is serialized using the following imp:

#[cfg(not(feature = "serde-float"))]
impl serde::Serialize for Decimal {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let value = crate::str::to_str_internal(self, true, None);
        serializer.serialize_str(value.0.as_ref())
    }
}

So in essence the implementation is the same but two different code paths. So which one should the casual user of rust_decimal rely upon?

I am using serde-with-str feature but frankly I don't remember how and when I plugged it in. I think that there was no default serialization for Decimal in the past, maybe it was added recently? Anyhow that feels confusing that there are two individual code paths exist that ultimately do the same thing. Documentation isn't very helpful neither.

It does however seem that deserialization works differently, i.e rust_decimal::serde::str only accepts strings, but without it JSON strings, integers and floats are parsed into Decimal.

@Tony-Samuels
Copy link
Collaborator

serde-*(e.g. serde-str) features allow you to override the default (de-)serialization strategy globally.
serde-with-* (e.g. `serde-with-str) features allow you to override the default (de-)serialization strategy on a case-by-case basis.

We would generally recommend using the serde-with-* features where possible.

As for which you want to use? That depends on how you want your types to be (de-)serialized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants