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}