serde-rs / serde

Serialization framework for Rust
https://serde.rs/
Apache License 2.0
9.06k stars 767 forks source link

Flattened nested structs throw deserialize error "invalid type: map, expected f64" when inner type contains a float #2748

Open adityabaradwaj opened 4 months ago

adityabaradwaj commented 4 months ago

~Update: this example works on other people's systems, but fails on mine.~ ~My specs:~ ~- M1 Max Macbook Pro running macOS Sonoma 14.5~ ~- rustc 1.76.0~ ~Already tried after running cargo clean, same result.~

Minimal reproducible example:

use serde::{Serialize, Deserialize};

fn main() {
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Outer {
        #[serde(flatten)]
        inner: Inner,
    }
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Inner {
        foo: f64,
    }

    let constructed = Outer {
        inner: Inner {
            foo: 1.0,
        },
    };

    let serialized = serde_json::to_string(&constructed).unwrap();
    println!("serialized: {serialized:?}");

    let deserialized: Outer = serde_json::from_str(&serialized).unwrap();
    println!("deserialized: {deserialized:?}");
}

Expected output

The struct correctly serializes and deserializes back into the original, with no errors

Observed output

serialized: "{\"foo\":1.0}"
thread 'main' panicked at temp.rs:25:65:
called `Result::unwrap()` on an `Err` value: Error("invalid type: map, expected f64", line: 1, column: 11)
stack backtrace:
   0: rust_begin_unwind
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/std/src/panicking.rs:645:5
   1: core::panicking::panic_fmt
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:72:14
   2: core::result::unwrap_failed
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/result.rs:1649:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/result.rs:1073:23
   4: temp::main
             at ./astra-server/examples/temp.rs:25:31
   5: core::ops::function::FnOnce::call_once
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Notes

This only happens when the inner type contains a f64 or f32. String and integer types seem to ser/deser without an error. The error also goes away when I remove #[serde(flatten)]

adityabaradwaj commented 4 months ago

See here for related issue: https://github.com/serde-rs/serde/issues/2623. This is only reproducible within certain crate/workspace setups. Presumably some other dependencies are affecting serde's behavior

adityabaradwaj commented 4 months ago

Update: my issue seems to controlled by the presence of a transitive dependency on the ethers and ethers-contract crates: https://github.com/serde-rs/serde/issues/2623#issuecomment-2133242549

Removing these dependencies results in correct behavior.

Still unclear what the underlying cause is though.

avkonst commented 3 months ago

The issue is caused by the serde_json arbitrary_precision feature being turned on. It passes when this feature is off and fails when it is on.

avkonst commented 3 months ago

that is the bug in the serde_json library