How to deserialize a subfield of a struct from the original struct's JSON with Serde?

后端 未结 2 922
迷失自我
迷失自我 2021-01-20 05:31

I want to have the Test::team_size attribute be deserialized from the data of Test object itself:

#[derive(Debug, Serialize, Deseri         


        
2条回答
  •  甜味超标
    2021-01-20 06:29

    As of Serde 1.0.34, you can now use #[serde(flatten)]:

    #[derive(Debug, Serialize, Deserialize)]
    struct Test {
        pub i: i64,
        #[serde(flatten)]
        pub team_size: TeamSize,
    }
    

    Before this, the easiest workaround would be to deserialize into a private helper type and restructure it as needed:

    #[macro_use]
    extern crate serde_derive;
    
    extern crate serde;
    extern crate serde_json;
    
    use serde::{Serialize, Serializer, Deserialize, Deserializer};
    
    #[derive(Debug)]
    pub struct TeamSize {
        pub min: i64,
        pub max: i64,
    }
    
    #[derive(Debug)]
    pub struct Test {
        pub i: i64,
        pub team_size: TeamSize,
    }
    
    // Private helper
    #[derive(Serialize, Deserialize)]
    struct Helper {
        pub i: i64,
        pub min: i64,
        pub max: i64,
    }
    
    impl Serialize for Test {
        fn serialize(&self, serializer: S) -> Result
            where S: Serializer
        {
            let helper = Helper {
                i: self.i,
                min: self.team_size.min,
                max: self.team_size.max,
            };
            helper.serialize(serializer)
        }
    }
    
    impl<'de> Deserialize<'de> for Test {
        fn deserialize(deserializer: D) -> Result
            where D: Deserializer<'de>
        {
            let helper = Helper::deserialize(deserializer)?;
            Ok(Test {
                i: helper.i,
                team_size: TeamSize {
                    min: helper.min,
                    max: helper.max,
                },
            })
        }
    }
    
    fn main() {
        let j = r#" { "i": -2, "min": 2, "max": 5 } "#;
    
        let de: Test = serde_json::from_str(j).unwrap();
        println!("{:#?}", de);
    
        let ser = serde_json::to_string_pretty(&de).unwrap();
        println!("{}", ser);
    }
    

提交回复
热议问题