Rust serde json反序列化任何数字

Rust serde json反序列化任何数字,rust,deserialization,json-deserialization,serde,Rust,Deserialization,Json Deserialization,Serde,我试图通过解析以下内容来结合和示例: { "secs": "12.34" } 或 进入结构: struct Duration { secs: u64, nanos: u32, } 其中,secs和nanos成员仅基于“secs”值设置。下面是我以这种方式实现自定义反序列化的非工作尝试,但我不确定如何为“secs”值委托string\u或\u int函数 use std::fmt; use std::marker::PhantomData; use std::str::Fr

我试图通过解析以下内容来结合和示例:

{
  "secs": "12.34"
}

进入结构:

struct Duration {
    secs: u64,
    nanos: u32,
}
其中,
secs
nanos
成员仅基于
“secs”
值设置。下面是我以这种方式实现自定义反序列化的非工作尝试,但我不确定如何为
“secs”
值委托
string\u或\u int
函数

use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use std::num::ParseIntError;
use serde::Deserialize;
use serde::de::{self, Deserializer, Visitor, MapAccess};

#[derive(Debug)]
struct Duration {
    secs: u64,
    nanos: u32,
}

impl<'de> Deserialize<'de> for Duration {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field { Secs };

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("`secs`")
                    }

                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
                    where
                        E: de::Error,
                    {
                        match value {
                            "secs" => Ok(Field::Secs),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct DurationVisitor;

        impl<'de> Visitor<'de> for DurationVisitor {
            type Value = Duration;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Duration")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Duration, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut secs = None;
                let mut nanos = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Secs => {
                            // TODO somehow delegate to string_or_int and
                            // set secs and nanos based on secs value.
                            // if secs is int:
                            //   secs = the int value
                            //   nanos = 0
                            // if secs is string:
                            //   secs = the int value * 10^(digit count right of '.')
                            //   nanos = digit count right of '.'
                            // e.g. given value of 12.34
                            //   secs = 1234
                            //   nanos = 2
                        }
                    }
                }
                let secs = secs.ok_or_else(|| de::Error::missing_field("secs"))?;
                let nanos = nanos.ok_or_else(|| de::Error::missing_field("nanos"))?;
                Ok(Duration {
                    secs,
                    nanos,
                })
            }
        }

        const FIELDS: &'static [&'static str] = &["secs"];
        deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor)
    }
}

fn string_or_int<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: Deserialize<'de> + FromStr<Err = ParseIntError>,
    D: Deserializer<'de>,
{
    struct StringOrInt<T>(PhantomData<fn() -> T>);

    impl<'de, T> Visitor<'de> for StringOrInt<T>
    where
        T: Deserialize<'de> + FromStr<Err = ParseIntError>,
    {
        type Value = T;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("string or int")
        }

        fn visit_str<E>(self, value: &str) -> Result<T, E>
        where
            E: de::Error,
        {
            Ok(FromStr::from_str(value).unwrap())
        }
    }

    deserializer.deserialize_any(StringOrInt(PhantomData))
}

fn main() {
    let json_raw = r#"{ "secs": "1.000" }"#;
    let j: Duration = serde_json::from_str(&json_raw).unwrap();
    println!("{:?}", j);
}

谢谢这是非常简单和容易阅读。我花了好几个小时试着让它工作。但是,它不处理
{“secs”:1234}
,但我将使用它来查看是否可以将其发送到。然后,您需要(使用您需要的任何数字处理)浮点操作
use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use std::num::ParseIntError;
use serde::Deserialize;
use serde::de::{self, Deserializer, Visitor, MapAccess};

#[derive(Debug)]
struct Duration {
    secs: u64,
    nanos: u32,
}

impl<'de> Deserialize<'de> for Duration {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field { Secs };

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("`secs`")
                    }

                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
                    where
                        E: de::Error,
                    {
                        match value {
                            "secs" => Ok(Field::Secs),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct DurationVisitor;

        impl<'de> Visitor<'de> for DurationVisitor {
            type Value = Duration;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Duration")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Duration, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut secs = None;
                let mut nanos = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Secs => {
                            // TODO somehow delegate to string_or_int and
                            // set secs and nanos based on secs value.
                            // if secs is int:
                            //   secs = the int value
                            //   nanos = 0
                            // if secs is string:
                            //   secs = the int value * 10^(digit count right of '.')
                            //   nanos = digit count right of '.'
                            // e.g. given value of 12.34
                            //   secs = 1234
                            //   nanos = 2
                        }
                    }
                }
                let secs = secs.ok_or_else(|| de::Error::missing_field("secs"))?;
                let nanos = nanos.ok_or_else(|| de::Error::missing_field("nanos"))?;
                Ok(Duration {
                    secs,
                    nanos,
                })
            }
        }

        const FIELDS: &'static [&'static str] = &["secs"];
        deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor)
    }
}

fn string_or_int<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: Deserialize<'de> + FromStr<Err = ParseIntError>,
    D: Deserializer<'de>,
{
    struct StringOrInt<T>(PhantomData<fn() -> T>);

    impl<'de, T> Visitor<'de> for StringOrInt<T>
    where
        T: Deserialize<'de> + FromStr<Err = ParseIntError>,
    {
        type Value = T;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("string or int")
        }

        fn visit_str<E>(self, value: &str) -> Result<T, E>
        where
            E: de::Error,
        {
            Ok(FromStr::from_str(value).unwrap())
        }
    }

    deserializer.deserialize_any(StringOrInt(PhantomData))
}

fn main() {
    let json_raw = r#"{ "secs": "1.000" }"#;
    let j: Duration = serde_json::from_str(&json_raw).unwrap();
    println!("{:?}", j);
}
use serde::{Deserialize, Deserializer};
use serde_json;

#[derive(Debug)]
struct Duration {
    secs: u64,
    nanos: u32,
}

#[derive(Deserialize)]
struct Raw<'a> {
    #[serde(borrow)]
    secs: StrOrNum<'a>,
}

#[derive(Deserialize)]
#[serde(untagged)]
enum StrOrNum<'a> {
    Str(&'a str),
    Num(u64),
}

impl<'de> Deserialize<'de> for Duration {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let raw = Raw::deserialize(deserializer)?;

        match raw.secs {
            StrOrNum::Str(s) => {
                if s.parse::<f64>().is_ok() {
                    let mut p = s.splitn(2, ".").fuse();
                    let secs = p.next().map_or(0, |s| s.parse().unwrap_or(0));
                    let frac = p.next().map_or(0, |s| s.parse().unwrap_or(0));
                    let nanos = frac.to_string().len() as u32;
                    let secs = secs * 10_u64.pow(nanos) + frac;
                    Ok(Duration { secs, nanos })
                } else {
                    Err(serde::de::Error::custom(format!("Not a valid decimal: \"{}\"", s)))
                }
            }
            StrOrNum::Num(secs) => Ok(Duration { secs, nanos: 0 }),
        }
    }
}

fn main() {
    let json_raw = r#"{ "secs": 1234 }"#;
    let j: Duration = serde_json::from_str(&json_raw).unwrap();
    println!("{:?}", j);
    let json_raw = r#"{ "secs": "12.34" }"#;
    let j: Duration = serde_json::from_str(&json_raw).unwrap();
    println!("{:?}", j);
    let json_raw = r#"{ "secs": "12.3.4" }"#;
    let j: Duration = serde_json::from_str(&json_raw).unwrap();
    println!("{:?}", j);
}