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