causal_hub/io/json.rs
1/// A trait for reading and writing JSON files.
2pub trait JsonIO {
3 /// Create an instance of the type from a JSON string.
4 ///
5 /// # Arguments
6 ///
7 /// * `json` - The JSON string to parse.
8 ///
9 /// # Returns
10 ///
11 /// An instance of the type.
12 ///
13 fn from_json(json: &str) -> Self;
14
15 /// Convert the instance to a JSON string.
16 ///
17 /// # Returns
18 ///
19 /// A JSON string representation of the instance.
20 ///
21 fn to_json(&self) -> String;
22
23 /// Create an instance of the type from a JSON file.
24 ///
25 /// # Arguments
26 ///
27 /// * `path` - The path to the JSON file.
28 ///
29 /// # Returns
30 ///
31 /// An instance of the type.
32 ///
33 fn read_json(path: &str) -> Self;
34
35 /// Write the instance to a JSON file.
36 ///
37 /// # Arguments
38 ///
39 /// * `path` - The path to the JSON file.
40 ///
41 fn write_json(&self, path: &str);
42}
43
44/// A macro to implement the `JsonIO` trait for a given type.
45#[macro_export]
46macro_rules! impl_json_io {
47 ($type:ty) => {
48 impl $crate::io::JsonIO for $type {
49 fn from_json(json: &str) -> Self {
50 // Parse the JSON string.
51 let json = serde_json::from_str(json).unwrap();
52 // Get the JSON Schema id.
53 let id = concat!(paste::paste! { stringify!([<$type:lower>]) }, ".schema.json");
54 // Load the JSON Schema validator.
55 let validator = jsonschema::options()
56 .with_retriever(&*$crate::assets::JSON_SCHEMA_RETRIEVER)
57 .build(&serde_json::json!({"$ref": id}))
58 .unwrap();
59 // Validate the JSON against the schema.
60 validator.validate(&json).unwrap();
61 // Convert the parsed JSON to the type.
62 serde_json::from_value(json).unwrap()
63 }
64
65 fn to_json(&self) -> String {
66 serde_json::to_string(self).unwrap()
67 }
68
69 fn read_json(path: &str) -> Self {
70 use std::{fs::File, io::BufReader};
71 // Open the file.
72 let file = File::open(path).unwrap();
73 // Create a buffered reader.
74 let reader = BufReader::new(file);
75 // Parse the JSON string.
76 let json = serde_json::from_reader(reader).unwrap();
77 // Get the JSON Schema id.
78 let id = concat!(paste::paste! { stringify!([<$type:lower>]) }, ".schema.json");
79 // Load the JSON Schema validator.
80 let validator = jsonschema::options()
81 .with_retriever(&*$crate::assets::JSON_SCHEMA_RETRIEVER)
82 .build(&serde_json::json!({"$ref": id}))
83 .unwrap();
84 // Validate the JSON against the schema.
85 validator.validate(&json).unwrap();
86 // Convert the parsed JSON to the type.
87 serde_json::from_value(json).unwrap()
88 }
89
90 fn write_json(&self, path: &str) {
91 use std::{fs::File, io::BufWriter};
92 let file = File::create(path).unwrap();
93 let writer = BufWriter::new(file);
94 serde_json::to_writer(writer, self).unwrap()
95 }
96 }
97 };
98}