json icon indicating copy to clipboard operation
json copied to clipboard

`arbitrary_precision` breaks float deserialisation in untagged enum

Open LDeakin opened this issue 1 year ago • 3 comments

Without arbitrary_precision the following runs without error:

#[derive(Debug, PartialEq, serde::Deserialize)]
#[serde(untagged)]
pub enum Num {
    Float(f64),
}

fn main() {
    assert_eq!(serde_json::from_str::<Num>(r#"1.0"#).unwrap(), Num::Float(1f64));
}

With arbitrary_precision, serde_json::from_str::<Num>(r#"1.0"#) fails with Error("data did not match any variant of untagged enum Num", line: 0, column: 0).

This issue is similar.

LDeakin avatar Jan 27 '24 03:01 LDeakin

See here also that the arbitary_precision feature in this case will cause the float to be parsed as a BTreeMap<String, Value> if one is available in the untagged enum: #1278

mplanchard avatar Jul 31 '25 17:07 mplanchard

There's a similar problem with enums using #[serde(tag = "..")]:

#![allow(unused)]

#[derive(serde::Deserialize)]
#[serde(tag = "type")]
enum Outer {
    A { inner: f64 },
}

fn main() {
    let raw = r#"
        {
            "type": "A",
            "inner": 0.5
        }
    "#;

    let parsed: Outer = serde_json::from_str(raw).unwrap();
}

Output:

thread 'main' panicked at src\main.rs:17:51:
called `Result::unwrap()` on an `Err` value: Error("invalid type: map, expected f64", line: 0, column: 0)

mtkennerly avatar Sep 16 '25 20:09 mtkennerly

The major problem with this is not so much that the feature is broken when combined with a variety of enum formats (although it is), but that any crate in the dependency tree that enables it can cause sudden inexplicable errors in what was previously perfect working code.

We've added a simple CI check to introspect the dependency tree for the feature, so that we can avoid production breakages like we had when we first encountered this. Replicating here in case anyone finds it useful:

if cargo tree --edges features --invert serde_json  --depth 1 --prefix none | 
    rg 'serde_json feature "arbitrary_precision"' 
then
    echo "found arbitrary_precision feature: figure out how to remove from dependencies"
    exit 1
else
    echo "...no serde_json arbitrary_precision found!"
fi

mplanchard avatar Sep 18 '25 14:09 mplanchard