You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not sure if I'm doing something wrong here, but I'm trying to write a type that can deserialize from either strings or integers.
Initially I did this using an untagged enumeration variant to do the heavy lifting - see here.
This worked fine until an upstream crate enabled the arbitrary_precision feature. I found #559 and serde-rs/serde#1183 on the topic, and so opted to implement a custom visitor as these seem to suggest the issue was in the untagged variant generation.
I therefore tried using a custom visitor
struct NumberVisitor<T> {
_phantom: PhantomData<T>,
}
impl<'de, T> serde::de::Visitor<'de> for NumberVisitor<T>
where
T: FromStr,
<T as FromStr>::Err: std::error::Error,
T: FromPrimitive,
{
type Value = NumberDeserialize<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("an integer or string")
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: Error,
{
T::from_i64(v)
.map(NumberDeserialize)
.ok_or_else(|| serde::de::Error::custom("cannot parse from i64"))
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
T::from_u64(v)
.map(NumberDeserialize)
.ok_or_else(|| serde::de::Error::custom("cannot parse from u64"))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: Error,
{
T::from_f64(v)
.map(NumberDeserialize)
.ok_or_else(|| serde::de::Error::custom("cannot parse from f64"))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
v.parse()
.map(NumberDeserialize)
.map_err(serde::de::Error::custom)
}
}
impl<'de, T> serde::Deserialize<'de> for NumberDeserialize<T>
where
T: FromStr,
<T as FromStr>::Err: std::error::Error,
T: FromPrimitive,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(NumberVisitor {
_phantom: Default::default(),
})
}
}
However, this runs into an issue where with arbitrary_precision, rather than calling visit_i* or similar, it calls visit_map with a custom map visitor for numeric types?! It would appear this then has a special-cased key of $serde_json::private::Number.
I'm not really sure what I'm supposed to do here, it would appear enabling arbitrary_precision makes it so that serializers don't decode numbers as numbers? Any help would be most appreciated.
As an aside whilst messing around with this I noticed enabling arbitrary_precision makes this fail
let input = r#"{"$serde_json::private::Number":"hello"}"#;
let value = serde_json::from_str::<serde_json::Value>(input).unwrap();
The text was updated successfully, but these errors were encountered:
I'm not sure if I'm doing something wrong here, but I'm trying to write a type that can deserialize from either strings or integers.
Initially I did this using an
untagged
enumeration variant to do the heavy lifting - see here.This worked fine until an upstream crate enabled the
arbitrary_precision
feature. I found #559 and serde-rs/serde#1183 on the topic, and so opted to implement a custom visitor as these seem to suggest the issue was in the untagged variant generation.I therefore tried using a custom visitor
However, this runs into an issue where with
arbitrary_precision
, rather than calling visit_i* or similar, it calls visit_map with a custom map visitor for numeric types?! It would appear this then has a special-cased key of$serde_json::private::Number
.I'm not really sure what I'm supposed to do here, it would appear enabling
arbitrary_precision
makes it so that serializers don't decode numbers as numbers? Any help would be most appreciated.As an aside whilst messing around with this I noticed enabling
arbitrary_precision
makes this failThe text was updated successfully, but these errors were encountered: