easy_json_serde/
lib.rs

1use serde::{de::DeserializeOwned, Serialize};
2use serde_json::{ser::PrettyFormatter, Serializer};
3use std::error::Error;
4use std::fs::{File, OpenOptions};
5use std::io::Read;
6use std::path::Path;
7
8pub trait EasyJsonSerialize {
9    fn save<P: AsRef<Path>, T: Serialize>(
10        path: P,
11        serializable_type: &T,
12        indentation_width: usize,
13    ) -> Result<File, Box<dyn Error>>;
14}
15
16impl EasyJsonSerialize for File {
17    fn save<P: AsRef<Path>, T: Serialize>(
18        path: P,
19        serializable_type: &T,
20        indentation_width: usize,
21    ) -> Result<File, Box<dyn Error>> {
22        let indentation_string = " ".repeat(indentation_width);
23        let formatter = PrettyFormatter::with_indent(indentation_string.as_bytes());
24        let file = OpenOptions::new().write(true).create(true).open(path)?;
25        let mut serializer = Serializer::with_formatter(&file, formatter);
26
27        serializable_type.serialize(&mut serializer)?;
28
29        Ok(file)
30    }
31}
32
33pub trait EasyJsonDeserialize<T> {
34    fn load(file: &mut File) -> Result<T, Box<dyn Error>>;
35}
36
37impl<T: DeserializeOwned> EasyJsonDeserialize<T> for T {
38    fn load(file: &mut File) -> Result<T, Box<dyn Error>> {
39        let mut json_string = String::new();
40        file.read_to_string(&mut json_string)?;
41
42        Ok(serde_json::from_str(&json_string)?)
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use std::fs::File;
49
50    use super::{EasyJsonDeserialize, EasyJsonSerialize};
51    use serde::{Deserialize, Serialize};
52
53    #[derive(Serialize, Deserialize, PartialEq, Debug)]
54    struct Dog {
55        name: String,
56        age: u8,
57    }
58
59    #[test]
60    fn test_serialization_and_deserialization() {
61        let rufus_original = Dog {
62            name: "Rufus".to_string(),
63            age: 10,
64        };
65
66        let file_name = "dog.json";
67        File::save(file_name, &rufus_original, 4).unwrap();
68
69        let mut json_file = File::open(file_name).unwrap();
70        let rufus_deserialized: Dog = Dog::load(&mut json_file).unwrap();
71
72        assert_eq!(rufus_original, rufus_deserialized)
73    }
74}