rschema_core/
schema.rs

1use serde::Serialize;
2
3use std::fs;
4
5use crate::{
6    Draft,
7    Result,
8    Schematic,
9};
10
11mod defs;
12pub mod r#type;
13
14pub use defs::Definitions;
15pub use r#type::Type;
16
17/// This is a structure representing the JSON schema itself.
18/// 
19/// ## Create Schema
20/// 
21/// See [the documentation top](https://docs.rs/rschema/latest/rschema/) for usage.
22/// 
23/// ## To JSON schema string
24/// 
25/// ```
26/// #[derive(Debug, Schematic)]
27/// struct Example {
28///     #[rschema(field(
29///         title = "Dummy",
30///         description = "Dummy field",
31///     ))]
32///     dummy: String,
33/// }
34/// 
35/// fn main() -> rschema::Result<()> {
36///     let schema_str = Schema::new::<Example>("Example")
37///         .to_string()?;
38/// 
39///     assert_eq!(
40///         schema_str,
41///         r#"{"title":"Example","type":"object","properties":{"dummy":{"title":"Dummy","description":"Dummy field","type":"string"}},"additionalProperties":false}"#
42///     );
43/// 
44///     Ok(())
45/// }
46/// ``` 
47/// 
48/// Use [`to_string_pretty`](fn@Schema::to_string_pretty) to generate as a pretty-prited string.
49/// 
50/// 
51#[derive(Debug, Serialize)]
52pub struct Schema {
53    #[serde(rename = "$schema")]
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub schema: Option<Draft>,
56
57    #[serde(rename = "$id")]
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub id: Option<String>,
60
61    pub title: String,
62
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub description: Option<String>,
65
66    #[serde(flatten)]
67    ty: Type,
68
69    #[serde(rename = "$defs")]
70    #[serde(skip_serializing_if = "Definitions::is_empty")]
71    defs: Definitions,
72}
73
74impl Schema {
75    /// Create a schema object from the given type `T`.
76    /// 
77    pub fn new<T: Schematic>(title: &str) -> Self {
78        Schema {
79            schema: None,
80            id: None,
81            title: title.into(),
82            description: None,
83            ty: T::__type_no_attr(),
84            defs: T::__defs(),
85        }
86    }
87
88    /// Add a description about this schema.
89    /// 
90    pub fn description(
91        &mut self,
92        description: impl Into<String>,
93    ) -> &mut Self {
94        self.description = Some(description.into());
95        self
96    }
97
98    /// Specify `$schema`.
99    /// 
100    pub fn schema(
101        &mut self,
102        schema: Draft,
103    ) -> &mut Self {
104        self.schema = Some(schema);
105        self
106    }
107
108    /// Specify `$id`.
109    /// 
110    pub fn id(
111        &mut self,
112        id: impl Into<String>,
113    ) -> &mut Self {
114        self.id = Some(id.into());
115        self
116    }
117
118    /// Generate a JSON schema string.
119    /// 
120    /// # Errors
121    /// 
122    /// Internally calls `serde_json::to_string`, so this can fail if it fails. [Read more](https://docs.rs/serde_json/latest/serde_json/fn.to_string.html)
123    /// 
124    pub fn to_string(&self) -> Result<String> {
125        let schema_str = serde_json::to_string(self)?;
126        Ok(schema_str)
127    }
128
129    /// Generate a pretty-printed JSON schema string.
130    /// 
131    /// # Errors
132    /// 
133    /// Internally calls `serde_json::to_string_pretty`, so this can fail if it fails. [Read more](https://docs.rs/serde_json/latest/serde_json/fn.to_string_pretty.html)
134    /// 
135    pub fn to_string_pretty(&self) -> Result<String> {
136        let schema_str = serde_json::to_string_pretty(self)?;
137        Ok(schema_str)
138    }
139
140    /// Write a JSON schema string to a file.
141    /// 
142    /// # Errors
143    /// 
144    /// This call can fail if its own `to_string` call or writing to a file fails.
145    /// 
146    pub fn write(
147        &self,
148        path: impl AsRef<std::path::Path>,
149    ) -> Result<()> {
150        let schema_str = self.to_string()?;
151        fs::write(path, schema_str)?;
152
153        Ok(())
154    }
155
156    /// Write a pretty-printed JSON schema string to a file.
157    /// 
158    /// # Errors
159    /// 
160    /// This call can fail if its own `to_string_pretty` call or writing to a file fails.
161    /// 
162    pub fn write_pretty(
163        &self,
164        path: impl AsRef<std::path::Path>,
165    ) -> Result<()> {
166        let schema_str = self.to_string_pretty()?;
167        fs::write(path, schema_str)?;
168
169        Ok(())
170    }
171}